Как сохранить листы в виде файлов CSV в формате UTF-8 в Excel для Mac 2011? - PullRequest
1 голос
/ 18 января 2011

У меня есть следующий Excel VBA скрипт, который я использую в Excel для Mac 2011 , чтобы экспортировать все листы файла Excel в файлы .csv.

Sub save_all_csv()
    On Error Resume Next
    Dim ExcelFileName As String
    ExcelFileName = ThisWorkbook.Name
    For Each objWorksheet In ThisWorkbook.Worksheets
        ExcelFileNameWithoutExtension = RemoveExtension(ExcelFileName)
        CsvFileName = ExcelFileNameWithoutExtension & "__" & objWorksheet.Name & ".csv"
        Application.DisplayAlerts = False
        objWorksheet.SaveAs Filename:="data:storage:original_excel:" & CsvFileName, FileFormat:=xlCSV, CreateBackup:=False
        Application.DisplayAlerts = True
    Next
    Application.DisplayAlerts = False
    Application.Quit
End Sub
Function RemoveExtension(strFileName As String)
    strFileName = Replace(strFileName, ".xlsx", "")
    strFileName = Replace(strFileName, ".xls", "")
    RemoveExtension = strFileName
End Function

Проблема в том, что они сохраняются как Western Mac OS Roman , который я не могу преобразовать в UTF-8 через PHP, поэтому я хотел бы, чтобы VBA сохранил эти файлы в формате UTF-8 во-первых.

alt text

Я нашел несколько решений для сохранения текста из VBA через объект Stream и с помощью CreateObject , но , очевидно, на Mac не возможно использовать CreateObject для прямой записи в файлы .

Как сохранить рабочие листы в виде файлов CSV в формате UTF-8 в Excel для Mac 2011?

Ответы [ 2 ]

2 голосов
/ 24 ноября 2015

У меня была такая же проблема, в конце концов я просто написал подпрограмму для кодирования в utf-8 . Этот код работает на моем MacBook Pro в Mac: Excel 2011. Просто используйте байтовый массив, созданный этой функцией, для вывода двоичного файла . В моем случае я обрабатываю тайский сценарий, чтобы автоматизировать использование превосходного синтезатора голоса Mac.

Private Function UTF8Encode(b() As Byte) As Byte()
    ' Function to convert a Unicode Byte array into a byte array that can be written to create a UTF8 Encoded file.
    ' Note the function supports the one, two and three byte UTF8 forms.
    ' Note: the MS VBA documentation is confusing. It says the String types only supports single byte charset
    '           however, thankfully, it does in fact contain 2 byte Unicode values.
    ' Wrote this routine as last resort, tried many ways to get unicode chars to a file or to a shell script call
    ' but this was the only way could get to work.
    ' RT Perkin
    ' 30/10/2015

    Dim b1, b2, b3 As Byte            ' UTF8 encoded bytes
    Dim u1, u2 As Byte                  ' Unicode input bytes
    Dim out As New Collection      ' Collection to build output array
    Dim i, j As Integer
    Dim unicode As Long

    If UBound(b) <= 0 Then
        Exit Function
    End If

    For i = 0 To UBound(b) Step 2
        u1 = b(i)
        u2 = b(i + 1)
        unicode = u2 * 256 + u1

        If unicode < &H80 Then
            ' Boils down to ASCII, one byte UTF-8
            out.Add (u1)
        ElseIf unicode < &H800 Then
            ' Two byte UTF-8
            ' Code path not tested
            b1 = &H80 Or (&H3F And u1)
            b2 = &HC0 Or (Int(u1 / 64)) Or ((&H7 And u2) * 4)
            out.Add (b2) ' Add most significant byte first
            out.Add (b1)
        ElseIf unicode < &H10000 Then
            ' Three byte UTF-8
            ' Thai chars are in this range
            b1 = &H80 Or (&H3F And u1)
            b2 = &H80 Or (Int(u1 / 64)) Or ((&HF And u2) * 4)
            b3 = &HE0 Or (Int(u2 / 16))
            out.Add (b3) ' Add most significant byte first
            out.Add (b2)
            out.Add (b1)
        Else
            ' This case wont arise as VBA strings are 2 byte. Which makes some Unicode codepoints uncodeable.
        End If

    Next

    Dim outBytes() As Byte
    ReDim outBytes(1 To out.Count)
    For j = 1 To out.Count
        outBytes(j) = CByte(out.Item(j))
    Next

    UTF8Encode = outBytes

End Function
1 голос
/ 18 января 2011

Я думаю, вы правы, что вам придется создавать файлы самостоятельно, и я совершенно уверен, что вы не можете использовать CreateObject для создания потоков.Однако вы можете захотеть использовать Open, Write и т. Д. (Множество примеров, но вот один ).Сначала я бы сделал очень маленький эксперимент, просто чтобы проверить, чем заканчивается кодировка.

Крис

...