Как сохранить данные нескольких документов в один csv

Автор celler, 10 марта 2015, 21:14

0 Пользователи и 1 гость просматривают эту тему.

JohnSUN

#15
Цитата: rami от 12 марта 2015, 10:33
Дублирование первого документа происходит от того, что в строке 101 отсутствует код: oSheets=oDoc.Sheets()
Bingo!
Цитата: rami от 12 марта 2015, 02:08
Вообще нужно сделать проверку очередного файла на "документообразность".
Точно! И реализовать это совсем не сложно. Например, вставить в 96-ой строке
If fileNames(i,1)="ods" Then
Массив, который возвращает ReadDirectories в нулевой колонке содержит полные путь-имя файла, а в первой - расширение (если третий и четвертый параметры - bcheckFileType и bGetByTitle - указаны False)
Или указать в вызове ReadDirectories еще один или два параметра - те самые Optional sFileContent() и Optional sExtension as String...

UPD. Да, так и есть. Изменение 18-ой строки на
fNames = ReadDirectories(ancDir, True,  False, False, Array("ods"))
и добавление в 101-ую
oSheets = oDoc.getSheets()
сделало макрос вполне работоспособным.
Ну, не хватает, конечно, протоколирования (файл такой-то - в 1-ый CSV записано 7 строк - во 2-ой CSV записано 1 строка -...- Ошибка: в книге 12 листов)... Но это уже оформительские заморочки, не так интересно, да и не очень-то и нужно
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

celler

#16
JohnSUN, rami, спасибо вам огромное, на мелких файлах заработало так как надо. Но попробовал подсунуть файлы по нескольку десятков тысяч строк и вылезла ошибка переполнения на стадии записи первого csv-файла. Это тот самый предел в миллион записей?

UPD: JohnSUN, не увидел твоё последнее сообщение, сейчас попробую поэкспериментировать.

JohnSUN

Цитата: celler от 12 марта 2015, 11:34Но попробовал подсунуть файлы по нескольку десятков тысяч строк и вылезла ошибка переполнения на стадии записи первого csv-файла. Это тот самый предел в миллион записей?
Нет, это не он... Писали бы в лист Calc'а - тогда да, тогда могли бы возникнуть проблемы. А свободного места на диске хватает?
Попробуй поставить точку останова где-то на 118-122 строках и посмотри состав массивов aRez и aRow, их размеры, значения sFNam и aCnt... Возможно, взглюкиваает на ReDim... В общем, смотреть надо. Или менять алгоритм
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

celler

#18
А как у вас там номера строк показываются? У меня почему-то на этом месте пустой столбец и ориентироваться невозможно.
В общем, с oSheets = oDoc.getSheets() в 101-й строке работает как надо кроме переполнения на больших файлах. У меня опыта с макросами нету, поэтому пытаюсь разобраться методом "тыка".

JohnSUN

Номера строк/колонок смотри внизу, на панели сообщений
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

rami

Цитата: celler от 12 марта 2015, 09:57А как у вас там номера строк показываются?
В меню Вид —> Номера строк

JohnSUN

Цитата: celler от 12 марта 2015, 11:57
работает как надо кроме переполнения на больших файлах.
Ну, значит нужно пересматривать алгоритм... Придется не накапливать все строки будущего csv-файла в массиве, а сразу сбрасывать их в нужный файл. То есть, сразу открыть семь файлов, данные каждого листа дописывать в соответствующий и в самом конце все семь закрыть... Это как вариант.
Другой вариант - если окажется, что взглюкивает ReDim на "усечении" массива результатов. Тогда придется выдернуть из библиотеки Tools эту самую процедуру SaveDataToFile и слегка её подправить - передать в неё ещё один параметр aCnt(i) и внутренний цикл крутить не до Ubound(DataList()), а именно до этой вот aCnt(i)...

Цитата: celler от 12 марта 2015, 11:57
У меня опыта с макросами нету, поэтому пытаюсь разобраться методом "тыка".
Дык, и мы тут не особо в них разбираемся  ;D Видишь, сколько "тыкаться" приходится?
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

celler

#22
Цитата: rami от 12 марта 2015, 10:08В меню Вид —> Номера строк
Спасибо!
Цитата: JohnSUN от 12 марта 2015, 10:15Ну, значит нужно пересматривать алгоритм... Придется не накапливать все строки будущего csv-файла в массиве, а сразу сбрасывать их в нужный файл. То есть, сразу открыть семь файлов, данные каждого листа дописывать в соответствующий и в самом конце все семь закрыть... Это как вариант.
Если бы я умел, то делал бы как можно проще - считать с первого файла первый лист и скинуть в csv, потом со второго файла туда же и так до последнего. Потом считать с первого файла второй лист и скинуть во второй csv и т.д. Можно даже на заголовки столбцов не обращать внимания, а копировать всё подряд вмести с ними.
Цитата: JohnSUN от 12 марта 2015, 09:50Попробуй поставить точку останова где-то на 118-122 строках и посмотри состав массивов aRez и aRow, их размеры, значения sFNam и aCnt..
А это я пока не умею.  :'(

rami

Ошибка в счётчике цикла i , он определён как Integer, больше 32767 циклов не сделает.

JohnSUN

#24
Цитата: celler от 12 марта 2015, 12:30
Попробуй поставить точку останова где-то на 118-122 строках и посмотри состав массивов aRez и aRow, их размеры, значения sFNam и aCnt.. - А это я пока не умею.  :'(
Ставишь курсор в любое место нужной строки кода и жмёшь F9 - включаешь или выключаешь точку останова. То же самое можно сделать и просто даблкликнув мышкой на белой полоске слева от кода. Нажатие F7 добавляет контрольное значение для просмотра. F8 - пошаговый проход по коду строка за строкой... Остальные кнопки можешь узнать, если поелозишь мышкой по кнопкам панели инструментов Макросы.
Цитата: rami от 12 марта 2015, 12:46
Ошибка в счётчике цикла i , он определён как Integer, больше 32767 циклов не сделает.
Точно! Та же самая фигня, что и с GetLastUsedRow! И ведь писать баг, похоже, никакого смысла нет...

Значит, celler, дальше всё очень просто.
В редакторе бэйсика залазишь в библиотеку Tools в модуль UCB. Находишь процедуру SaveDataToFile (это начиная с 214 строки). Копируешь все эти 22 строки кода в модуль crtCSV, в конец. Удаляешь строчки
Dim FileChannel as Integer
и
Dim oStreamString as Object
они не нужны, эти переменные в процедуре не используются.
Меняешь строку
Dim i as Integer
на
Dim i as Long
Запускаешь макрос на больших файлах и убеждаешься, что теперь-то всё работает без ошибок.
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

celler

#25
Цитата: JohnSUN от 12 марта 2015, 10:54дальше всё очень просто
Сейчас попробую, спасибо!

UPD Всё работает и на больших файлах! Огромное спасибо!  :beer:

rami

JohnSUN, а у меня к тебе нескромный вопрос: почему документ .csv созданый макросом весит 1.4 мега, а . csv созданый офисом "сохранить как..." весит 462 кило. Начальные данные одинаковы. Количество строк 20тыс.

JohnSUN

Причин может быть масса, можем пока только строить догадки.
Скорее всего, "виноват" какой-то из параметров фильтра (см.картинку).
Макрос пишет в юникоде - меняем кодировку, скажем, на 1251 и существенно меняется размер.
Макрос каждое поле "окавычивает", на всякий случай - а на 22 полях в строке это 44 кавычки. Не ставим галочку на "Текстовые значения в кавычках" и экономим немножко байтов. Ну, и т.д.

А что говорит FC?
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне

rami

Цитата: JohnSUN от 12 марта 2015, 13:55А что говорит FC?
Он с Маком не разговаривает.
Кодировка только UTF-8. Настройки я не редактирую, они по умолчанию. При разделителе ; в макросе и 38тыс. строк в исходном .ods создаётся(без проблем) .csv на 2.7 мега, а LibreOffice вешается от печали :'( в момент открытия .csv Пришлось в макросе заменить ; на ,
Если созданый макросом документ .csv "сохранить как..." или даже просто "сохранить" вес уменьшается в три раза. Попробуй открыть созданый макросом документ .csv и пересохранить, что получится у тебя?

JohnSUN

Жаль тебя разочаровывать, но против фактов не попрёшь... Заметное уменьшение размера - только при смене кодировки
Владислав Орлов aka JohnSUN
Благодарить-не зазорно.
Подарить благо создателям офиса, нашему ресурсу, мне