大家好,我是你们的Excel小助手,今天要给大家分享一个超酷的小技巧,绝对能让你成为办公室里的最靓的仔!
大家都知道Excel表格复制成txt后无法带边框,然后发现复制粘贴总是格式乱七八糟。别着急,今天我就要教你一个神奇的VBA技巧,一键导出带有管道符的TXT文件,格式整整齐齐,再也不怕txt显示不了表格啦!

代码示例
下面是实现这一功能的VBA代码,你只需要将这段代码插入到Excel的VBA编辑器中,然后运行它,即可将选中的表格区域导出为带有制表符的TXT文件。
'====================================================== '将选中区域导出为带有制表符的TXT文件,注意需要使用等宽字体(如新宋体)才能正确显示 '参数:selection,可通过给Rng重新赋值来修改要导出的区域 '生成的TXT文件路径和名称与当前文档一样 '====================================================== Public StrLength As Integer '每个单元格一行所容纳的最大字符长度 Public rng As Range '要导出的单元格区域 Sub Table() Dim arr() As Variant, brr() As Variant Dim row As Integer, Col As Integer Dim i As Integer, j As Integer, k As Integer Dim Max As Integer Dim cell As Range, cell2 As Range Dim StartRow As Integer, EndRow As Integer Dim StartCol As Integer, EndCol As Integer Dim L As Integer Dim n As Integer Dim width As Integer Dim crr As Variant Dim ColWidth() As Variant '导出后所有列的字节数 StrLength = 16 '字符长度限制为16,即32个字节【此数值限制最大列宽】 Set rng = Selection '设置导出的区域,默认是选中的区域 If rng.count <= 1 Then MsgBox "不支持独立单元格的导出!": Exit Sub '错误提示 '设置带制表符的数组的大小 arr = rng.Value row = UBound(arr, 1) * 2 + 1 Col = UBound(arr, 2) * 2 + 1 ReDim arr(1 To row, 1 To Col) '生成四角框 arr(1, 1) = "┌" arr(1, Col) = "┐" arr(row, 1) = "└" arr(row, Col) = "┘" '生成内框和内部数据 For i = 2 To row - 1 For j = 2 To Col - 1 Select Case i Mod 2 Case 1 If j Mod 2 = 1 Then arr(i, j) = "┼" If j Mod 2 = 0 Then arr(i, j) = "─" Case 0 If j Mod 2 = 1 Then arr(i, j) = "│" If j Mod 2 = 0 Then arr(i, j) = rng.Cells(i / 2, j / 2) End Select Next j Next i '生成外框 For i = 2 To row - 1 If i Mod 2 = 0 Then arr(i, 1) = "│" arr(i, Col) = "│" Else arr(i, 1) = "├" arr(i, Col) = "┤" End If Next i For j = 2 To Col - 1 If j Mod 2 = 0 Then arr(1, j) = "─" arr(row, j) = "─" Else arr(1, j) = "┬" arr(row, j) = "┴" End If Next j '求列宽 ReDim ColWidth(1 To Col) '单元格从右向左倒序,便于计算合并单元格的字节数 For j = Col - 1 To 2 Step -2 Max = 0 For i = 2 To row - 1 Step 2 '数据所在行 With rng.Cells(i / 2, j / 2) Select Case .MergeCells Case False '不属于合并单元格 L = LenB(StrConv(arr(i, j), vbFromUnicode)) Case True '属于合并单元格 If .MergeArea.Column = .Column Then width = 0 brr = .MergeArea.Value If UBound(brr, 2) > 1 Then '列数>1 For k = 2 To (UBound(brr, 2) - 1) * 2 width = width + ColWidth(j + k) Next k '这个值应该是合并单元格上方的非合并单元格的字节数 L = CellWidth(i, j, rng, ColWidth) - 2 * (UBound(brr, 2) - 1) - width Else '列数=1 L = CellWidth(i, j, rng, ColWidth) End If Else L = 0 End If End Select End With If Max < L Then Max = L Next i If Max Mod 2 = 1 Then Max = Max + 1 '字节数必须是偶数 ColWidth(j) = Application.Min(Max, StrLength * 2) If Max < StrLength * 2 Then ColWidth(j) = Max Else ColWidth(j) = StrLength * 2 End If Next j '整理格式 For j = 2 To Col - 1 Step 2 '遍历字符所在列 ' If j Mod 2 = 0 Then '字符所在列 For i = 1 To row L = LenB(StrConv(arr(i, j), vbFromUnicode)) '字节数 Select Case i Mod 2 Case 0 '如果是偶数行,即数据所在行 Set cell = rng.Cells(i / 2, j / 2) If Not cell.MergeCells Then If ColWidth(j) > L Then _ arr(i, j) = arr(i, j) & String(ColWidth(j) - L, " ") ElseIf cell.MergeArea.Column = cell.Column Then If CellWidth(i, j, rng, ColWidth) > L Then _ arr(i, j) = arr(i, j) & String(CellWidth(i, j, rng, ColWidth()) - L, " ") ElseIf cell.MergeArea.Column <> cell.Column Then arr(i, j) = "" End If Case 1 '如果是奇数行,即制表符行 ' L = LenB(StrConv(arr(i, j), vbFromUnicode)) '字节数 If ColWidth(j) >= L Then arr(i, j) = arr(i, j) & String((ColWidth(j) - L) / 2, "─") Else arr(i, j) = "" '如果制表符字节数比max大则代表这一列的单元格内容都为空,则删除制表符 End If End Select Next i ' End If Next j '处理合并单元格 For Each cell In rng If cell.MergeCells Then '利用数组来找到合并单元格的起始位置和结束位置 brr = cell.MergeArea.Value StartRow = cell.MergeArea.row - rng.row + 1 StartCol = cell.MergeArea.Column - rng.Column + 1 EndRow = StartRow + UBound(brr, 1) EndCol = StartCol + UBound(brr, 2) '调用处理合并单元格子函数 merge arr, StartRow, EndRow, StartCol, EndCol End If Next '处理换行符 For Each cell In rng n = Len(cell) - Len(Replace(cell, Chr(10), "")) If n > 0 Then i = (cell.row - rng.row + 1) * 2 j = (cell.Column - rng.Column + 1) * 2 width = CellWidth(i, j, rng, ColWidth) / 2 crr = Split(cell.Value, Chr(10)) For k = 0 To n - 1 L = Len(crr(k)) Select Case L Case Is <= width crr(k) = crr(k) & String(width - L, " ") Case Is > width crr(k) = crr(k) & String(width - (L Mod width), " ") End Select Next k arr(i, j) = Join(crr, "") ' Debug.Print arr(i, j), LenB(StrConv(arr(i, j), vbFromUnicode)) [a30] = arr(i, j) End If Next '处理换行 ' 从倒数第2行开始遍历所有数据所在行,避免插入新行后对arr中未整理的行号造成影响 i = UBound(arr, 1) Do While i > 1 Max = 0 For j = 2 To Col - 1 Step 2 '数据所在列 L = LenB(StrConv(arr(i, j), vbFromUnicode)) width = CellWidth(i, j, rng, ColWidth) If L > width And width <> 0 Then n = Int(Len(arr(i, j)) / (width / 2)) '换行数 If Max < n Then Max = n End If Next j If Max > 0 Then InsertLine arr, i, Max '插入行 i = i - 1 '跳至下一个数据行 Loop SaveTxt arr End Sub '====================================================== '将表格中的某个区域导出TXT文档 '参数:数组变量 '生成的TXT文件路径和名称与当前文档一样 '====================================================== Sub SaveTxt(ByVal arr As Variant) Dim path As String Dim i As Integer, j As Integer Dim Str As String path = ThisWorkbook.path & "\" & Left(ThisWorkbook.Name, _ Application.Find(".", ThisWorkbook.Name) - 1) & ".txt" Open path For Output As #1 For i = 1 To UBound(arr, 1) For j = 1 To UBound(arr, 2) Str = Str & arr(i, j) Next j Print #1, Str Str = "" Next i Close #1 End Sub '处理合并单元格的制表符格式 Sub merge(ByRef arr() As Variant, ByVal stRow As Integer, _ ByVal edRow As Integer, ByVal stCol As Integer, ByVal edCol As Integer) Dim Row1 As Integer Dim Row2 As Integer Dim Col1 As Integer Dim Col2 As Integer Dim i As Integer, j As Integer '数组中的位置 Row1 = stRow * 2 - 1 Col1 = stCol * 2 - 1 Row2 = edRow * 2 - 1 Col2 = edCol * 2 - 1 '处理内部线框 For i = Row1 + 1 To Row2 - 1 For j = Col1 + 1 To Col2 - 1 If i Mod 2 <> 0 Then arr(i, j) = String(LenB(StrConv(arr(i, j), vbFromUnicode)), " ") ElseIf j Mod 2 <> 0 Then arr(i, j) = "" End If Next j Next i '处理上下框线 For i = Col1 + 1 To Col2 - 1 arr(Row1, i) = Replace(arr(Row1, i), "┼", "┴") arr(Row1, i) = Replace(arr(Row1, i), "┬", "─") arr(Row2, i) = Replace(arr(Row2, i), "┼", "┬") arr(Row2, i) = Replace(arr(Row2, i), "┴", "─") Next i '处理左右框线 For i = Row1 + 1 To Row2 - 1 arr(i, Col1) = Replace(arr(i, Col1), "┼", "┤") arr(i, Col1) = Replace(arr(i, Col1), "├", "│") arr(i, Col2) = Replace(arr(i, Col2), "┼", "├") arr(i, Col2) = Replace(arr(i, Col2), "┤", "│") Next i End Sub Sub InsertLine(ByRef arr() As Variant, ByVal InsRow As Integer, ByVal n As Integer) Dim i As Integer, j As Integer Dim brr() As Variant Dim Length As Integer, L As Integer Dim row As Integer, Col As Integer '插入后表格的行数和列数 row = UBound(arr, 1) + n Col = UBound(arr, 2) ReDim brr(1 To row, 1 To Col) '把arr的内容逐个复制到brr中,同时插入换行的内容 For i = 1 To row For j = 1 To Col Select Case i '复制插入之前的行 Case Is <= InsRow brr(i, j) = arr(i, j) '处理插入行的内容 Case Is <= InsRow + n Select Case j Mod 2 Case Is = 1 '奇数列即制表符列,直接复制上一行的内容 brr(i, j) = arr(InsRow, j) Case Is = 0 '偶数列即数据所在列,按行号截取字符串内容 Length = LenB(StrConv(arr(InsRow, j), vbFromUnicode)) '字符串字节数 L = CellWidth(InsRow, j, rng, ColWidth) / 2 '单元格字节数/2 If Length <= L * 2 Then brr(i, j) = String(Length, " ") Else brr(i, j) = Mid(arr(InsRow, j), L * (i - InsRow) + 1, L) ' Debug.Print arr(InsRow, j),LenB(StrConv(arr(InsRow, j), vbFromUnicode)) '使插入的单元格字节长度符合要求 Length = LenB(StrConv(brr(i, j), vbFromUnicode)) If Length < L * 2 Then brr(i, j) = brr(i, j) & String(L * 2 - Length, " ") '处理原单元格的字符内容 brr(InsRow, j) = Left(arr(InsRow, j), L) Length = LenB(StrConv(brr(InsRow, j), vbFromUnicode)) If Length < L * 2 Then brr(InsRow, j) = brr(InsRow, j) & _ String(L * 2 - Length, " ") End If End Select '复制插入行之后的内容 Case Else brr(i, j) = arr(i - n, j) End Select Next j Next i '将brr的值赋给arr ReDim arr(1 To row, 1 To Col) arr = brr End Sub 'Function IsFirstCol(ByVal i As Integer, ByVal j As Integer, Rng As Range) ' With Rng.Cells(i / 2, j / 2) ' If .MergeArea.Column = .Column Then ' IsFirstCol = True ' Else ' IsFirstCol = False ' End If ' End With 'End Function '单元格宽度 Function CellWidth(ByVal i As Integer, ByVal j As Integer, rng As Range, ColWidth As Variant) Dim width As Integer Dim brr() As Variant Dim L As Integer Dim k As Integer Dim strL As Integer With rng.Cells(i / 2, j / 2) strL = LenB(StrConv(.Value, vbFromUnicode)) If .MergeCells Then If .MergeArea.Column = .Column Then width = 0 brr = .MergeArea.Value If UBound(brr, 2) > 1 Then For k = 2 To (UBound(brr, 2) - 1) * 2 width = width + ColWidth(j + k) Next k L = 2 * (UBound(brr, 2) - 1) + width + ColWidth(j) If L < strL Then L = Application.Max(StrLength * 2, L) Else L = Application.Max(ColWidth(j), Application.Min(StrLength * 2, strL)) End If Else L = 0 End If Else L = ColWidth(j) End If End With If i Mod 2 = 1 Then L = ColWidth(j) If L Mod 2 = 1 Then L = L + 1 CellWidth = L End Function
一点小提示
在导出之前,记得选中你想要导出的表格区域哦!
导出的txt文件字体需要选择等宽字体(如新宋体),格式才能对齐哟!
嘿,是不是觉得这个小魔法很有趣?以后再也不用为分享Excel表格而烦恼了,一键导出,整整齐齐,妈妈再也不用担心我分享数据啦!如果你还有其他有趣的VBA小技巧,快快留言分享给大家吧!
发表回复