Страницы: 1 2 След.
RSS
Перенос макроса из 32 бит в 64 бит
 
Добрый день.
Есть код макроса, который работает в версии 32 бит, но в 64 отказывается. может кто-то сможет подсказать, что надо поменять? Речь идет о версии Эксель 2016
Нашел справку про это https://msdn.microsoft.com/ru-ru/VBA/Language-Reference-VBA/articles/64-bit-visual-basic-for-applica...

У меня та ки не получилось адаптировать, нужна Ваша помощь...
Код
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
 
dennn, добрый день.
Цитата
работает в версии 32 бит, но в 64 отказывается
что пишет?

Почему вы решили, что проблема именно в разрядности системы? Я не вижу в коде api функций. У меня при x64 код отработал молча.
 
Jungl, ничего не пишет. Просто зависает во время выполнения и все.
А у вас какая версия эксель? Я тестирую на 16.0.4549 2016 года
 
Нужен пример, работающий в 32-разрядной версии и не работающий в 64-разрядной.
Владимир
 
sokol92, , файйл доступен по ссылке. - https://yadi.sk/d/tVhFhVFI3Pqs3d
Сюда не выкладываю, так как он большой. А возможно, именно размер и важен.
Если сделать новый файл и вставить макрос, то все выполняется, но в файле старом отказывается это делать.
 
Код
    For Each rngRow In rngRange.Rows
        objStream.WriteText CsvFormatRow(rngRow)
    Next rngRow
Вы копируете в .csv - 85800 строк - построчно! Предполагаю и в 32 разрядной версии время будет не меньше.
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, выполняется все это буквально за 1 минуту, а то и меньше. А тут по 5 минут может висеть и результата в итоге нет.
Изменено: dennn - 20.11.2017 12:47:54
 
Еще раз  - вы копируете в .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. Если исходная информация не содержит символов, не отображаемых в кодовой странице по умолчанию, то эффективнее решить задачу в два этапа:
  1. сформировать csv-файл в "родной" кодировке (Windows-1251)
  2. изменить кодировку сформированного ранее файла на UTF8 (Windows-65001)
Первый этап выполняется "мухой" встроенными средствами Excel. Второй этап также занимает секунды при использовании того же объекта Ado.Stream, см., например, здесь.

Успехов!
Изменено: sokol92 - 21.11.2017 09:45:31 (Уточнена формулировка)
Владимир
 
Цитата
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 тыс. строк)?
У меня отрабатывает так же долго, тогда странно, почему у вас быстрее.
Изменено: bedvit - 20.11.2017 17:49:06
«Бритва Оккама» или «Принцип Калашникова»?
 
Проверяли на нескольких машинах. Одна из них: 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 - не дождался - закрыл.
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
dennn написал:
Может просто сможете подсказать, что поправить в этом коде, чтобы он заработал на 64 версии?)
Сохранить файл в формате .csv, штатными средствами. В Excel 2010 x64 они есть (при сохранении выберите нужный формат). Можно делать программно.
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, я знаю что есть. Но в моем случае это не так удобно, как макрос.
 
Сделайте сохранение макросом (если вам нужно сохранить весь файл или лист, а не пару выбранных строк). Думаю это новая тема.
К примеру так:
Код
    ActiveWorkbook.SaveAs Filename:="..нужный_путь..EXPORT.csv", FileFormat:=xlCSV ' или
    ThisWorkbook.SaveAs Filename:="..нужный_путь..EXPORT.csv", FileFormat:=xlCSV 'или
    Workbooks("Экспорт пример.xlsm").SaveAs Filename:="..нужный_путь..EXPORT.csv", FileFormat:=xlCSV
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
bedvit написал:
Вы открывали файл EXPORT.csv, и у вас там 85 тыс. строк?
Из сообщения #12: Время формирования файла из 85801 строки (последняя пустая) - 30 сек.
Владимир
 
sokol92, значит у меня и у вас по разному отрабатывает.
«Бритва Оккама» или «Принцип Калашникова»?
 
Спасибо за предложенные варианты!
К сожалению, после выполнения этих макросов существующий эксель файл превращается в csv файл, а мне надо чтобы был просто экспорт, а открытым оставался эксель файл.
 
Вам нужно что бы оставался открытый лист в Excel и его копия сохранялась в csv? Это то же не сложно, делаете копию листа в новый файл, сохраняет его по третьему способу. Текущий лист остаётся открытым. Попробуйте через макроридер, не получится завтра я вам набросаю.
«Бритва Оккама» или «Принцип Калашникова»?
 
Код отсюда создает CSV из примера за 6 сек. (of2010 /32).
Перекодирование (с того же сайта), думаю, еще секунду попросит.
Изменено: RAN - 20.11.2017 21:05:11
 
Цитата
bedvit написал:
Попробуйте через макроридер, не получится завтра я вам набросаю.
Был бы очень признателен!
Последний код попробовал, но он также превращает файл эксель в csv, и разделитель - запятая, а надо - точка с запятой.
Мне уже даже не так важно, чтобы это было в UTF-8, а просто экспорт в новый файл.
Изменено: dennn - 21.11.2017 06:54:40
 
Справедливости ради должен сделать еще пару замечаний.

Если в исходной информации есть символы, не отображаемые в кодовой странице по умолчанию (например, буквы греческого алфавита), то на первом этапе в сообщении #10 можно использовать юникод (UTF16, Windows-1200). Внес соответствующее уточнение.

Цитата
dennn написал:
В последней версии эксель 2016 есть специальный формат сохранения - csv в формате UTF-8.

Любопытно. В документации про это не написано.

Цитата
dennn написал:
Последний код попробовал, но он также превращает файл эксель в csv, и разделитель - запятая, а надо - точка с запятой.
В указанных в сообщении #22 макросах в качестве разделителя полей по умолчанию используется именно точка с запятой.
Владимир
 
Если у вас региональные настройки по умолчанию - с нужным вам разделителем элементов списка (по умолчанию он ";")
Код
'с разделителем как в региональных настройках, стандартный механизм сохранения
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

Создание CSV - 2 сек.
Изменено: bedvit - 21.11.2017 12:53:14
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, вроде работает. Спасибо!

А вот потом перекодировать в UTF-8 сложно?
 
Цитата
sokol92 написал:
Любопытно. В  документации  про это не написано.
Точно было. Мне даже на скрине показывали те, у кого стояла последняя версия. Пока быстро не удалось найти в каком обновлении это было - поищу попозже, если актуально.
А вы мне лучше подскажите, как мне макрос-то запускать в 64 бит.
Вы рекомендации дали, но они мне не под силу...
Да и вообще не совсем даже понял, почему в 32 все гуд работает, а в 64 - нет(
 
Моё решение работает в Excel x64 - быстро, не подходит?
«Бритва Оккама» или «Принцип Калашникова»?
 
bedvit, если вопрос с кодировкой решим в UTF-8, то конечно подойдет!
 
Цитата
dennn написал:
Да и вообще не совсем даже понял, почему в 32 все гуд работает, а в 64 - нет(

Мы в ходе экспериментов не установили, что разрядность Excel влияет на результат - см. сообщение #2. Было отмечено негативное поведение макроса в определенных конфигурациях (в том числе, 32-разрядных в сообщении #11).
Для перекодировки, по-прежнему, рекомендую посмотреть готовый макрос здесь.
Владимир
Страницы: 1 2 След.
Наверх