У меня та ки не получилось адаптировать, нужна Ваша помощь...
Код
Option Explicit
Const strDelimiter = """"
Const strDelimiterEscaped = strDelimiter & strDelimiter
Const strSeparator = ";"
Const strRowEnd = vbCrLf
Const strCharset = "utf-8"
Function CsvFormatString(strRaw As String) As String
Dim boolNeedsDelimiting As Boolean
boolNeedsDelimiting = InStr(1, strRaw, strDelimiter) > 0 _
Or InStr(1, strRaw, Chr(10)) > 0 _
Or InStr(1, strRaw, strSeparator) > 0
CsvFormatString = strRaw
If boolNeedsDelimiting Then
CsvFormatString = strDelimiter & _
Replace(strRaw, strDelimiter, strDelimiterEscaped) & _
strDelimiter
End If
End Function
Function CsvFormatRow(rngRow As Range) As String
Dim arrCsvRow() As String
ReDim arrCsvRow(rngRow.Cells.Count - 1)
Dim rngCell As Range
Dim lngIndex As Long
lngIndex = 0
For Each rngCell In rngRow.Cells
arrCsvRow(lngIndex) = CsvFormatString(rngCell.Text)
lngIndex = lngIndex + 1
Next rngCell
CsvFormatRow = Join(arrCsvRow, ";") & strRowEnd
End Function
Sub CsvExportRange( _
rngRange As Range, _
Optional strFileName As Variant _
)
Dim rngRow As Range
Dim objStream As Object
If IsMissing(strFileName) Or IsEmpty(strFileName) Then
strFileName = Application.GetSaveAsFilename( _
InitialFileName:=ActiveWorkbook.Path & "\" & rngRange.Worksheet.Name & ".csv", _
FileFilter:="CSV (*.csv), *.csv", _
Title:="Export CSV")
End If
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = 2
objStream.Charset = strCharset
objStream.Open
For Each rngRow In rngRange.Rows
objStream.WriteText CsvFormatRow(rngRow)
Next rngRow
objStream.SaveToFile strFileName, 2
objStream.Close
End Sub
Sub CsvExportSelection()
CsvExportRange ActiveWindow.Selection
End Sub
Sub CsvExportSheet()
Dim wksSheet As Worksheet
Set wksSheet = ActiveSheet
CsvExportRange wksSheet.UsedRange
MsgBox "CSV file, with active sheet is ready."
End Su
sokol92, , файйл доступен по ссылке. - https://yadi.sk/d/tVhFhVFI3Pqs3d Сюда не выкладываю, так как он большой. А возможно, именно размер и важен. Если сделать новый файл и вставить макрос, то все выполняется, но в файле старом отказывается это делать.
Еще раз - вы копируете в .csv - 85800 строк - построчно! и в 32 и в 64 разрядных версиях это выполняется долго. Я не стал ждать, выключил. Разрядность здесь не причем.
Оставьте 10 строк, и в Excel x64 - это отрабатывает быстро (и работает), как и в х32. На 85800 строк виснит и в х32 и в х64 по причине написанной выше.
Уважаемый dennn! Эффект, описанный Вами, воспроизводится. Проверили на Excel 2007, 2010(32), 2013(32) - макрос выполняется относительно быстро, на 2016(64) "не работает" (см. ниже). Разрешите Вам дать несколько рекомендаций.
Если Вы используете макрос, который работает (может работать) больше 30 секунд, то обязательно показывайте "мультфильм". В Вашем примере достаточно выдавать в макросе CsvExportRange через каждые 500 (например) строк сообщение о количестве обработанных строк посредством свойства Application.StatusBar. Сделав так, мы видим, что при выполнении в среде Excel 2016(64) макрос моментально обрабатывает первые 10 000 строк (на Вашем компьютере показатели могут быть иными), далее интервал между сообщениями все время увеличивается и в районе 30 000 строк ждать новое сообщение уже можно минутами.
Если готовить о сути алгоритма, то Вы построчно (более 85000 раз) обращаетесь к методу WriteText объекта Ado.Stream. В то же время, исходная задача у Вас - вывести лист (или) диапазон в csv-формате в кодировке UTF8. Если исходная информация не содержит символов, не отображаемых в кодовой странице по умолчанию, то эффективнее решить задачу в два этапа:
сформировать csv-файл в "родной" кодировке (Windows-1251)
изменить кодировку сформированного ранее файла на UTF8 (Windows-65001)
Первый этап выполняется "мухой" встроенными средствами Excel. Второй этап также занимает секунды при использовании того же объекта Ado.Stream, см., например, здесь.
sokol92 написал: Excel 2007, 2010(32), 2013(32) - макрос выполняется относительно быстро
выполнял на excel 2010x32, win7, выполняется так же долго на 85 тыс. строк, как и в 2016х64. Вы точно выгружали 85 тыс. строк?
Цитата
sokol92 написал: Сделав так, мы видим, что при выполнении в среде Excel 2016(64) макрос моментально обрабатывает первые 10 000 строк (на Вашем компьютере показатели могут быть иными), далее интервал между сообщениями все время увеличивается и в районе 30 000 строк ждать новое сообщение уже можно минутами.
sokol92, вы хотите сказать Excel х32 отрабатывает не так, как Excel x64, а быстрее (на 85 тыс. строк)? У меня отрабатывает так же долго, тогда странно, почему у вас быстрее.
Проверяли на нескольких машинах. Одна из них: Excel 2010 14.0.7190.5000 (32), Win 7(64), SP1. Время формирования файла из 85801 строки (последняя пустая) - 30 сек. Конфигурация Excel 2010(64) у нас отсутствует.
sokol92, спасибо за проделанную работу! Дело в том, что у меня данные на листе обновляются 1 раз в час через PQ, поэтому надо делать экспорт именно из эксель файла. Если сохранить в csv, а потом перекодировать - то не так быстро получается, как сейчас с макросом. К Тому ЖЕ! В последней версии эксель 2016 есть специальный формат сохранения - csv в формате UTF-8. Но у меня пока версии этого офиса нет, а покупать - накладно. Еще важный момент - после сохранения файла из эксель в csv - открывается именно файл csv, а эксель пропадает, что не совсем удобно. У меня эксель стоит этот на сервере, поэтому хотел просто обновить Эксель без изменения логики, то есть чтобы был экспорт в UTF-8 через макрос. Сам Макрос писал не я - нашел на этом форуме, поэтому не могу его корректировать, так как нет практически этих знаний.
Может просто сможете подсказать, что поправить в этом коде, чтобы он заработал на 64 версии?)
Вы открывали файл EXPORT.csv, и у вас там 85 тыс. строк? У меня Win 7(64), SP1, Excel 2010 (32) 14.0.6112.5000 отрабатывает дольше чем Win 7(64), SP1, Excel 2016 (64) 16.0.4266.1001 в несколько раз, т.е. х64 быстрее х32 (для справедливости скажу, что система быстрее под х64). Просто добавил счетчик и посмотрел. Выгружает мин за 5 в Excel x64, x32 - не дождался - закрыл.
Спасибо за предложенные варианты! К сожалению, после выполнения этих макросов существующий эксель файл превращается в csv файл, а мне надо чтобы был просто экспорт, а открытым оставался эксель файл.
Вам нужно что бы оставался открытый лист в Excel и его копия сохранялась в csv? Это то же не сложно, делаете копию листа в новый файл, сохраняет его по третьему способу. Текущий лист остаётся открытым. Попробуйте через макроридер, не получится завтра я вам набросаю.
bedvit написал: Попробуйте через макроридер, не получится завтра я вам набросаю.
Был бы очень признателен! Последний код попробовал, но он также превращает файл эксель в csv, и разделитель - запятая, а надо - точка с запятой. Мне уже даже не так важно, чтобы это было в UTF-8, а просто экспорт в новый файл.
Справедливости ради должен сделать еще пару замечаний.
Если в исходной информации есть символы, не отображаемые в кодовой странице по умолчанию (например, буквы греческого алфавита), то на первом этапе в сообщении #10 можно использовать юникод (UTF16, Windows-1200). Внес соответствующее уточнение.
Цитата
dennn написал: В последней версии эксель 2016 есть специальный формат сохранения - csv в формате UTF-8.
Если у вас региональные настройки по умолчанию - с нужным вам разделителем элементов списка (по умолчанию он ";")
Код
'с разделителем как в региональных настройках, стандартный механизм сохранения
Sub save_csv()
With Application: .ScreenUpdating = 0: .DisplayAlerts = 0: End With
Sheets("EXPORT").Copy
ActiveWorkbook.SaveAs Filename:=".....\EXPORT.csv", FileFormat:=xlCSV, Local:=True
ActiveWindow.Close False
With Application: .ScreenUpdating = 1: .DisplayAlerts = 1: End With
End Sub
sokol92 написал: Любопытно. В документации про это не написано.
Точно было. Мне даже на скрине показывали те, у кого стояла последняя версия. Пока быстро не удалось найти в каком обновлении это было - поищу попозже, если актуально. А вы мне лучше подскажите, как мне макрос-то запускать в 64 бит. Вы рекомендации дали, но они мне не под силу... Да и вообще не совсем даже понял, почему в 32 все гуд работает, а в 64 - нет(
dennn написал: Да и вообще не совсем даже понял, почему в 32 все гуд работает, а в 64 - нет(
Мы в ходе экспериментов не установили, что разрядность Excel влияет на результат - см. сообщение #2. Было отмечено негативное поведение макроса в определенных конфигурациях (в том числе, 32-разрядных в сообщении #11). Для перекодировки, по-прежнему, рекомендую посмотреть готовый макрос здесь.