我需要将许多(例如超过 100 个)法语、分号分隔的 CSV 文件导入到 Excel 中,我有点懒于手动进行转换,因此我寻求一种自动执行转换的方法。我使用的是 MacBook(苹果芯片,如果有的话),所以不幸的是我无法使用内置的 PowerQuery 功能。我对 VBA 一无所知,所以方便的衡量标准逐渐失控。幸运的是,到目前为止,我自己的固执和谷歌一直为我提供了良好的服务——我最终使用了 Reddit 上发布的这个解决方案。它最终需要进行编辑才能在当年实际运行。这就是我最终得到的结果:
Sub Select_File_Or_Files_Mac()
Dim MyPath As String
Dim MyScript As String
Dim MyFiles As String
Dim MySplit As Variant
Dim N As Long
Dim Fname As String
Dim mybook As Workbook
On Error Resume Next
MyFiles = AppleScriptTask("excelCSVselect.scpt", "select_files", "")
On Error GoTo 0
If MyFiles <> "" Then
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
MySplit = Split(MyFiles, Chr(10))
For N = LBound(MySplit) To UBound(MySplit)
'Get file name only and test if it is open
Fname = Right(MySplit(N), Len(MySplit(N)))
' - InStrRev(MySplit(N), _
' ":", , 1))
On Error Resume Next
Set mybook = Workbooks.Open(MySplit(N))
On Error GoTo 0
Next
Worksheets("Sheet1").Activate
With ActiveSheet.QueryTables.Add( _
Connection:="TEXT;" & Fname, _
Destination:=Range("A1"))
.FieldNames = True
.RowNumbers = False
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SaveData = True
.AdjustColumnWidth = True
.TextFilePromptOnRefresh = False
.TextFilePlatform = 65001
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileSemicolonDelimiter = True
' .TextFileColumnDataTypes = Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
End With
End If
End Sub
excelCSVselect.scpt AppleScript 的功能与 reddit 帖子的 MacScript 函数几乎完全相同。从多个在线资源拼凑而成。它允许您选择多个 .csv,但将其转换为具有 POSIX 文件路径的列表,即不使用冒号:
on convertListToString(theList, theDelimiter)
set AppleScript's text item delimiters to theDelimiter
set theString to theList as string
set AppleScript's text item delimiters to ""
return theString
end convertListToString
on select_files()
set filelist to {}
set CSV_files to choose file with prompt "Pick CSV Files to convert" with multiple selections allowed
repeat with a in CSV_files
set end of filelist to (POSIX path of a as string)
end repeat
return convertListToString(filelist, "\n")
end select_files
select_files()
问题? 所有应该由 QueryTables.Add 函数处理的格式化实际上并没有发生。我为每个 CSV 获得一个新工作簿,但每个 CSV 行都是一个丑陋的块。据我所知,
.TextFileSemicolonDelimiter = True
没有运行。另一件重要的事情是确保法语特殊字符正确显示。理论上,.TextFilePlatform = 65001
应该这样做;它不是。发生的另一件不理想的事情是,我认为该程序不知何故卡在了最后一部分,因为运行它后,如果不退出 Excel 工作表,我就无法再返回到 VBA 项目。
正如我上面所说,我几乎不知道自己在做什么。但我在查看 Microsoft 文档时认为,这些 QueryTable 点属性之一(例如 .BackgroundQuery)可能是无关的并且会扰乱输出。我不再认为情况是这样的,通过删除太多这些方法,我给自己带来了一个神秘的 400 错误,我无法修复,所以我就让它们保留。我认为这与刷新过程有关。不是说我明白这意味着什么! :')
在(不明智地)花了一整天时间解决这个问题之后,我设法让现场分离几乎 100% 按照我想要的方式工作!
我没有意识到链接的解决方案同时做两件事 - 当原始 Reddit 海报实际上想要将数据加载到工作表中时,他们用
Workbooks.Open
打开了一个新工作簿。
Sub Select_File_Or_Files_Mac()
Dim MyFiles As String
Dim MySplit As Variant
Dim N As Long
Dim Fname As String
Dim ws As Worksheet
Dim newData As QueryTable
On Error Resume Next
MyFiles = AppleScriptTask("excelCSVselect.scpt", "select_files", "")
On Error GoTo 0
If MyFiles <> "" Then
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
MySplit = Split(MyFiles, Chr(10))
For N = LBound(MySplit) To UBound(MySplit)
'Get file name only
Fname = Right(MySplit(N), Len(MySplit(N)))
Set ws = Worksheets.Add
Set newData = ws.QueryTables.Add( _
Connection:="TEXT;" & Fname, _
Destination:=ws.Range("A1"))
With newData
.BackgroundQuery = False ' Change to False to prevent freezing
.Refresh BackgroundQuery:=False
.TextFileParseType = xlDelimited
.TextFileStartRow = 1
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFilePlatform = 65001
.PreserveFormatting = True
.TextFileSemicolonDelimiter = True
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.RefreshStyle = xlInsertDeleteCells
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0 ' No refresh period
End With
DoEvents ' Allow Excel to process events
Next N
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End If
End Sub
但是,我仍然无法正确编码特殊字符。我读到,Excel 忽略 UTF-8 编码并使用 UTF-16LE 时可能会发生一些情况。我会选择相信这一切正在发生以应对。
无论是什么原因,由于正确使用特殊字符来阅读法语文本非常重要,所以我只是使用 Python/Pandas 来代替。顺利了很多。 (也许应该从那开始。) ́\_(ツ)_/́