Инкапсуляция вывода в двойные кавычки

Я написал макрос, который принимает входной файл CSV, обновляет некоторые поля с жестко заданными настройками, а затем снова сохраняет файл как CSV.

Код для всего этого работает. Однако выходной файл должен иметь кавычки, окружающие все поля, чтобы наш собственный графический интерфейс правильно читал его.

например строка, содержащая: TestStrips1, 1, 0,8, 0, -0,2

необходимо отформатировать как: «TestStrips1», «1», «0,8», «0», «-0,2»

Вот часть моего кода, которая связана с этим. Использование жестко заданных номеров строк/столбцов, потому что они не изменятся. cellHold и newCell являются DIMd, как варианты выше, и я использую их как способ заставить конкатенацию работать так, как задумано:

For i = 1 To 5
    For j = 1 To 40
        cellHold = NewBook.Sheets(1).Cells(j, i).Value
        'NewBook.Sheets(1).Cells(j, i).NumberFormat = "@"
        newCell = Chr(34) & cellHold & Chr(34)
        NewBook.Sheets(1).Cells(j, i) = newCell
    Next j
Next i
If Dir(fPath & "OffsetCoordinates_orig.csv") <> "" Then Kill (fPath & "OffsetCoordinates_orig.csv")
wbOrig.SaveAs Filename:=fPath & "OffsetCoordinates_orig.csv", FileFormat:=xlCSV
wbOrig.Close
If Dir(fPath & "OffsetCoordinates.csv") <> "" Then Kill (fPath & "OffsetCoordinates.csv")
NewBook.SaveAs Filename:=fPath & "OffsetCoordinates.csv", FileFormat:=xlCSV
NewBook.Close
MsgBox ("Your Offset file has been updated successfully. Please see " & fPath & " for your new file.")  

Я пробовал это с установкой числового формата в строку и без нее, и, похоже, это не влияет на вывод. Как ни странно, этот код выдает результат, который на самом деле выглядит правильно при просмотре в Excel (кавычки вокруг каждой ячейки), но при просмотре с помощью notepad++ на самом деле вокруг каждого элемента есть ТРОЙНЫЕ кавычки, например:

"""TestStrips1""","""1""","""-1,2""","""0,6""","""0,4"""

Когда я смотрю на родительский файл, который я пытаюсь эмулировать, при просмотре в Excel в ячейке нет кавычек, но в блокноте ++ вывод соответствует назначению с кавычками вокруг каждого элемента.

Мне неясно, является ли это проблемой форматирования или Excel добавляет дополнительные символы кавычек.


В основном решено с помощью следующего кода, на который указал Тим, другие ответы тоже выглядели полезными, но это было сделано первым.

    For i = 1 To 5
        For j = 1 To 40
            cellHold = NewBook.Sheets(1).Cells(j, i).Value
            NewBook.Sheets(1).Cells(j, i).NumberFormat = "@" 'not necessary?
            newCell = cellHold
            NewBook.Sheets(1).Cells(j, i) = newCell
            Debug.Print (NewBook.Sheets(1).Cells(j, i).Value)
        Next j
    Next i
    If Dir(fpath & "OffsetCoordinates_orig.csv") <> "" Then Kill (fpath & "OffsetCoordinates_orig.csv")
    wbOrig.SaveAs Filename:=fpath & "OffsetCoordinates_orig.csv", FileFormat:=xlCSV
    wbOrig.Close
    If Dir(fpath & "OffsetCoordinates.csv") <> "" Then Kill (fpath & "OffsetCoordinates.csv")
'    NewBook.SaveAs Filename:=fPath & "OffsetCoordinates.csv", FileFormat:=xlCSV
    Application.ActiveSheet.Range("A1:E40").Select
    Call QuoteCommaExport(fpath)
    Application.DisplayAlerts = False
    NewBook.Close
    Application.DisplayAlerts = True
    MsgBox ("Your Offset file has been updated successfully. Please see " & fpath & " for your new file.")
End Sub

Sub QuoteCommaExport(fpath)
'Comments from Microsoft's solution 
' Dimension all variables. 
    Dim DestFile As String
    Dim FileNum As Integer
    Dim ColumnCount As Integer
    Dim RowCount As Integer

    ' Prompt user for destination file name.
    DestFile = fpath & "OffsetCoordinates.csv"

    ' Obtain next free file handle number.
    FileNum = FreeFile()

    ' Turn error checking off.
    On Error Resume Next

    ' Attempt to open destination file for output.
    Open DestFile For Output As #FileNum

    ' If an error occurs report it and end.
    If Err <> 0 Then
        MsgBox "Cannot open filename " & DestFile
        End
    End If

    ' Turn error checking on.
    On Error GoTo 0

    ' Loop for each row in selection.
    For RowCount = 1 To 40

        ' Loop for each column in selection.
        For ColumnCount = 1 To 5

            ' Write current cell's text to file with quotation marks.
            Print #FileNum, """" & Selection.Cells(RowCount, _
              ColumnCount).Text & """";

            ' Check if cell is in last column.
            If ColumnCount = Selection.Columns.Count Then
                ' If so, then write a blank line.
                Print #FileNum,
            Else
                ' Otherwise, write a comma.
                Print #FileNum, ",";
            End If
        ' Start next iteration of ColumnCount loop.
        Next ColumnCount
    ' Start next iteration of RowCount loop.
    Next RowCount

    ' Close destination file.
    Close #FileNum
End Sub

Предоставленный Microsoft код (увиденный в подразделе QuoteCommaExport) работает в основном так, как предполагалось, за исключением того, что у меня было очень странное поведение, когда дата неправильно копировалась в выходной файл 'csv'. Вместо того, чтобы отображаться как в исходном файле, эта ячейка копировалась как «#######». Я понял, что когда я просматривал код, я иногда вручную изменял размер столбца с датой, чтобы он соответствовал точкам останова (чтобы убедиться, что в ячейке была правильная дата, а не просто набор символов #). Всякий раз, когда я это делал, он правильно копировал содержимое. Таким образом, код копирует отображаемые символы, а не содержимое ячейки. Изменение размера столбцов перед вызовом Sub исправило поведение.


person Brad Keusch    schedule 02.01.2020    source источник
comment
Моя единственная мысль заключается в том, что, возможно, у вас включено автозаполнение в NPP, и поэтому кавычки утраиваются? Ваш код выглядит нормально, поскольку он должен выводить только "foo". Что происходит, когда вы Debug.Print ActiveCell.Value, где ActiveCell — это правильно отформатированная ячейка?   -  person jclasley    schedule 02.01.2020
comment
В окне Immediate он правильно отображается как foo. Вот почему я подумал, что, возможно, это связано с SaveAs. Я попробовал несколько других CSV-файлов, включая xlCSVUTF8 и xlCSVMSDOS, но это, похоже, не имело никакого значения.   -  person Brad Keusch    schedule 02.01.2020
comment
Excel добавит кавычки по своему усмотрению (например, если значение содержит запятую). Он также будет экранировать любые найденные двойные кавычки, удвоив их, а затем также добавит кавычки вокруг значения экранированной ячейки: вот почему вы видите тройные двойные кавычки.   -  person Tim Williams    schedule 02.01.2020
comment
docs.microsoft.com/ en-us/office/устранение неполадок/excel/   -  person Tim Williams    schedule 02.01.2020
comment
Когда вы открываете свой исходный файл в Блокноте, есть ли кавычки?   -  person FaneDuru    schedule 02.01.2020
comment
Использование связанного кода Тима от Microsoft работает, за исключением того, что я не совсем понимаю, как взаимодействовать с целевым файлом #FileNum, поэтому я не могу закрыть его, не предложив пользователю сохранить. Кажется ошеломляющим, что Microsoft признает, что это проблема, и не реализует ее изначально в excel/vba. Я вижу этот новый выходной файл с кавычками вокруг каждого элемента в АЭС и блокноте и без кавычек при открытии в Excel.   -  person Brad Keusch    schedule 03.01.2020
comment
Как и на связанной странице, Close #FileNum закроет файл. Неудивительно, что Excel по умолчанию сохраняет CSV-файлы без кавычек, если только они не требуются (например, когда значения содержат запятые) — спецификация (хотя она и может быть немного расплывчатой) не требует, чтобы все значения были заключены в кавычки.   -  person Tim Williams    schedule 03.01.2020
comment
Close #FileNum закрывает файл, но запрашивает ввод данных пользователем, чтобы сохранить файл или нет, есть ли способ отключить это? Я пытался установить для оповещений на дисплее значение false, но это не сработало. Спасибо за вашу помощь в этом! Является ли правильным этикетом изменить вопрос с помощью этого решения?   -  person Brad Keusch    schedule 03.01.2020


Ответы (3)


Экспорт .CSV из Excel — непростая задача. Способ экспорта странным образом связан с вашими настройками локализации. Сначала я пытался воспроизвести вашу ситуацию, но не смог. Все экспортировалось как положено (имею ввиду с простыми кавычками). Затем, повозившись с локализацией «Регион» (дополнительные настройки: разделитель списка, десятичный символ, символ группировки цифр), я смог воспроизвести поведение, на которое вы ссылались. После этого я не мог вернуться к своим первоначальным настройкам... Поэтому я попытался найти другой надежный способ создания файла .CSV. I выполняется очень быстро, так как все делается в памяти:

Dim arr As Variant, arr1() As Variant, i As Long, j As Long, sh As Worksheet
  Set sh = NewBook.Sheets(1)
  'Add quotes and input the necessary range in an array
  arr = sh.Range("A1:E40").value
  ReDim arr1(4, UBound(arr))
  For i = 1 To UBound(arr)
     For j = 0 To 4
        arr1(j, i - 1) = Chr(34) & arr(i, j + 1) & Chr(34)
     Next
  Next i
  'create .CSV comma delimited
  Dim newF As String, FileNum, strRow As String
  newF = "C:\YourFile.csv"
  FileNum = FreeFile()
  Open newF For Output As #FileNum
    For i = 0 To UBound(arr) - 1
        strRow = arr1(0, i) & "," & arr1(1, i) & "," & arr1(2, i) & _
                                        arr1(3, i) & "," & arr1(4, i)
        Print #FileNum, strRow
    Next i
  Close #FileNum

Для вашего (пример) диапазона он запускается почти мгновенно... Пожалуйста, позаботьтесь о том, чтобы изменить переменную newF на ваше реально необходимое полное имя .CSV. Код, конечно, можно улучшить, чтобы он автоматически определял экспортируемый диапазон, если не всегда тот, что из вашего примера...

person FaneDuru    schedule 03.01.2020

Вы можете использовать Powershell, чтобы добавить кавычки вокруг чисел.

  • Файл должен быть закрыт, если вы хотите перезаписать его
  • В файле должна быть строка заголовка для этого решения.
  • Открытие файла и сохранение его из Excel удалит двойные кавычки.

Sub AddQuotesToCSV(ByVal FileName As String, Optional ByVal NewFileName As String)
    Const PowershellCommand As String = "Powershell " & vbNewLine & _
        "$P = Import-Csv -Path '@FileName'" & vbNewLine & _
        "$P | Export-Csv -Path '@NewFileName' -NoTypeInformation -Encoding UTF8"
    Dim Command As String

    Command = Replace(PowershellCommand, "@FileName", FileName)
    Command = Replace(Command, "@NewFileName", IIf(Len(NewFileName) > 0, NewFileName, FileName))

    CreateObject("WScript.Shell").Exec Command
End Sub
person TinMan    schedule 02.01.2020

Вы также можете использовать регулярное выражение:

Sub FF()
    Dim s, re, fso, txt
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set re = CreateObject("VBScript.RegExp")
    re.Global = True: re.Pattern = "([^,$\r\n]+)"
    Set txt = fso.OpenTextFile("C:\Temp\1\test.csv") 'Reading
    s = re.Replace(txt.ReadAll(), """$1""")
    txt.Close
    Set txt = fso.OpenTextFile("C:\Temp\1\test.csv", 2) 'Updating
    txt.Write s: txt.Close
End Sub
person JohnyL    schedule 03.01.2020