Добрый день, носители знаний о любимой программе А есть ли у рабочего листа свойство, которое указывает на объем данных, хранимых этим листом? Не хочется загружать код отдельным вычислением. Может уже есть свойство, хранящее нужные сведения? Задача возникла из-за необходимости автоматически дробить книгу на части. Т.е выгружать из нее в отдельные файлы те листы с данными, которые разрослись свыше некоторого, заранее установленного предела. Поскольку структура листов различна, а их содержимое меняется довольно таки динамично, то хотелось бы иметь элементарный оценочный механизм, сканирующий каждый лист на предмет "не пора ли нам пора".
Поддерживаю, тоже интересно Иногда ошибка в макросе приводит к заполнению всех строк(столбцов) вплоть до самого конца и не всегда в них значения. а просто форматы или не известные даже локальной версии Excel Файл по размеру разрастается до десятков мегабайт при минимуме полезной информации лечу последовательным удалением листов(вкладок) или процедурой "clear", прописывая её на каждую вкладку на ненужные ячейки.
Или просто код в процессе отладки. Но да, соглашусь, тут не в размере листа дело, а в работе кода с файлом. Самое забавное, что иногда файл с макросом начинает разрастаться как на дрожжах даже если код отрабатывает без ошибок, и объём данных на листах не меняется.
Абсолютно не принципиально. Вопрос скорее политический и условный - пора не пора. А то файл базы данных так разросся, что промежуточное сохранение заставляет ждать по минуте, пока он перепишется на диск. Вот и думаю, что нужно какие-то листы периодически помечать на перенос в отдельные файлы и подгружать их обратно только по мере их надобности. потому что балластных данных\листов, которые могут не использоваться в текущей сессии работы с файлом, - 90%. При этом плодить лишние файлы с листами, на которых данных с гулькин нос, нет никакого смысла. Т.е нужнен условный, можно даже относительный, а не абсолютный оценочный механизм веса различных листов.
БМВ, В макросе это будет не тривиально реализовано и по быстродействию не айс, т.к задействует FSO. Проще уж тогда выделить рабочую область и через specialcells и len подсчитывать число символов. Но это опять же - скрытый цикл со всеми вытекающими по быстродействию. Когда один лист - оно не проблема. А когда листов сотни, да и операция проводится с некоторой периодичностью, это уже подгрузочка ЦП.
Я в VBA не очень, но не быстрее будет запихать таблу с листа в оперативку и глянуть сколько памяти она займет? Или такого функционала нет? Оно правда будет отличаться от того что сохранено в структуре xml, но все же.
PooHkrd, Ну я во внутреннем устройстве оболочки Эксэеля не шарю, но предполагаю, что открытый файл и так уже в оперативке частично или целиком. Только вот нам то показывется весь объем его данных, занятых оболочкой Экселя в ОП. А какая часть за каким элементом, хрен знает, возможно ли вытащить инфо?
Андрей VG написал: Пора прощаться с детством в Excel .
Андрей, прощание исключено. Я уже дано это понял. Причина банальна. Эксель в себе содержит мощный практически безграничный инструментарий, который при расставании придется ручками прописывать так же бесконечно в каждом своем приложении. Это очень трудоемко и потребует кучу времени на изобретение ведлосипедов, уже созданных в эксель. У меня мощнейший обработчик моей мощной БД весит всего 2,7 Мб. Будь он отдельным приложением, то весил бы мегов 300 и не факт, что мне удалось бы за жизнь прописать и отладить все те возмозможности, которые он дает. Я давно обратил внимание, что любой язык программирования не может быть полностью универсальным и эффективным для решения абсолютно всех вопросов. У Екселя есть свои изъяны. Да, он не тянет быструю обработку таких мощных объемов данных. Но плюсы тоже имеет несомненные. Я их назвал. Поэтому переход к любой системе - это всегда определенные жертвы и определенный компромисс. И естественно мастерство программиста, выкручивающегося и скглаживающего продуманными алгоритмами недостатки конкретного движка. Несколько раз серьезно раздумывая о том, уходить или не уходить от Экселя, я все же пришел к выводу, что уход в целом для реализации моих задач не целесообразен.
Neufazendnik написал: по быстродействию не айс, т.к задействует FSO
не аргумент, вопрос ,как часто дергать. FSO не такой и тормоз в сравнении с распаковкой архива. Если научить просто получать список файлов и размер их, то совсем простая операция.
БМВ написал: Если научить просто получать список файлов и размер их, то совсем простая операция.
Моя база данных в том числе управляет всеми нужными мне файлами (не обязательно экселевскими), в том числе фиксирует их размер и дату изменения и помогает их архивировать. Так что учить ее ничему не нужно. У меня уже есть соответствующие процедуры, включая контроль за версией файлов. Но все это я нахожу слишком длинным и сложным путем для решения столь простого вопроса. Должно быть более разумное и изящное решение.
Вопрос в быстродействии. Имеющийся вариант называется - для бешенной собаки семь верст не крюк. Мне нужно изящное решение, а не гора процедур и 1000 строк кода вместо 10 символов. По идее Эксель должен где-то хранить размеры своих объектов. Ведь он оперирует памятью, выделяемой под их хранение\отображение.
Цитата
БМВ написал: это может относится к части где хранить данные, а не чем их обрабатывать.
С этим согласен. Но тут пока нет проблемы, если их хранить тупо в экселевском формате и не заморачиваться, бегая впереди паровоза. Ну будет отдельный каталог с файлами эксель. Делов то... Не изящно, странно, за то работает А на большее не претендую, т.к по сей день езжу на Москвиче 2140 и поьзую WinХP и Windows Commander на ряде своих компов и меня это вполне устраивает! Не вижу смысла в прогрессе ради прогресса, если существующие инструменты на 100% выполняют свои задачи.
Neufazendnik написал: Мне нужно изящное решение, а не гора процедур и 1000 строк кода вместо 10 символов.
странно конечно это читать, ну я в VBA почти ноль, как минимум так себя позиционирую, по этому спорить не стану. Действительно что последует после res = shell.exec …. в тяжком цикле парсинга нескольких строк , поиска нужных и получения размера мне сказать трудно. Думаю десятка два точно будет, что явно больше 10 символов.
Neufazendnik написал: Ведь он оперирует памятью, выделяемой под их хранение\отображение
Только Microsoft не озаботилась ни предоставлением доступа в объектной модели для VBA, ни свободным доступом к документации API вызовов dll исполняемого кода. P. S. Новая тема для курилки
БМВ написал: что последует после res = shell.exec …. в тяжком цикле парсинга нескольких строк , поиска нужных и получения размера мне сказать трудно.
Вызов команды Dir, мне кажется, будет в 100 раз более медленной операцией, (т.к это далеко не тривиальная операция по своей сути)нежели этот элементарный цикл по расшифровке содержимого каталога. Кстати, не вникал, как там современно через FSO это делается. У меня это реализовано именно вызовом досовской Dir и перенаправлением результата в txt файл, который dir генерирует в дурацкой кодировке, в которой часть символов "улетают" в некорректность при попытке их считывать штатными процедурами чтения из текстового файла. Поэтому приходится еще и анализировать ASCII код каждого символа и через CASE ретранслировать. В общем, зоопарк отдыхает с расшифровкой некоторых свойств оглавления каталога. Уже не помню, каких именно. Реализовано было лет 15 назад. Работает и работает по сей день без вопросов и я не парюсь, как оно там и чего.
Sub GetSheetsSize()
Set WshShell = CreateObject("WScript.Shell")
cmd = """C:\Program Files\7-Zip\7z.exe"" l ""C:\Temp\Copy of 1_1.xlsm"" xl\worksheets"
Set WshExec = WshShell.exec(cmd)
While WshExec.Status = 0
' конечно хотелось бы SLEEP
Wend
strOutput = Application.WorksheetFunction.Trim(WshExec.StdOut.ReadAll)
a = Split(strOutput, vbCrLf)
For i = 0 To UBound(a)
b = Split(a(i), " ")
If UBound(b) > 4 Then
If InStr(1, b(5), "xl\worksheets\") > 0 And InStr(1, b(5), "_rels") = 0 Then
Debug.Print Replace(b(5), "xl\worksheets\", "") & "-" & b(3)
End If
End If
Next i
End Sub
Без массива уложился в 18 строк.
Цитата
Neufazendnik написал: Реализовано было лет 15 назад
и это через .exec тоже проще. Вы попробуйте, может есть методы лучше чем 2140 :-). FSO тоже не так плох, как мне кажется :-)
БМВ написал: Вы попробуйте, может есть методы лучше чем 2140 :-).
Пробовал. Сравнить есть с чем объективно. НО! Консерватор. Не расходую новых ресурсов на уже решенные вопросы без острой нужды. За альтернативу благодарю. Я возьму на заметочку - скопирую себе в альбом заготовочек, чтобы в случае чего по справке долго не рыскать!
Function GetSheetsSize(FileName As String)
' Return array with codesheet names and size of them
'7zip must be installed and path mast be corrected
ReDim C(1, 0)
Set WshShell = CreateObject("WScript.Shell")
cmd = """C:\Program Files\7-Zip\7z.exe"" l """ & FileName & """ xl\worksheets"
Set WshExec = WshShell.exec(cmd)
While WshExec.Status = 0
Wend
strOutput = Application.WorksheetFunction.Trim(WshExec.StdOut.ReadAll)
a = Split(strOutput, vbCrLf)
j = -1
For i = 0 To UBound(a)
b = Split(a(i), " ")
If UBound(b) > 4 Then
If InStr(1, b(5), "xl\worksheets\") > 0 And InStr(1, b(5), "_rels") = 0 Then
j = j + 1
ReDim Preserve C(1, j)
C(0, j) = Replace(b(5), "xl\worksheets\", "")
C(1, j) = CLng(b(3))
End If
End If
Next i
GetSheetsSize = C
End Function
БМВ, Чтот я в дебри залез. Разбираю первый Ваш код. Нет у меня зипа. Переиначил код под Rar: cmd = """C:\Program Files\WinRAR\RAR.exe"" I=xl\worksheets -r F:\DIN\Базаэксперименты.xlsm" Вызов возвращает пустую строку. Пробую отдельно из командной строки запускать. Отрабатывает и закрывается окно. Не вижу результата. Пробую просто раром открыть вручную - он не открывает xlsm. Оно и логично. Если расширение вручную сменить - откроет. А так вроде б и правильно ругается на тип файла. Короче, запутался я.
Похоже, в моем случае самым разумным будет ввести лимит не на вес листа, а на число записей на листе. Учитывая, что на любом листе у меня есть слолбец с ключевым индексом, задача подсчета будет тривиальной. А в спецтаблице пропишу для каждого из листов лимит, при превышении которого лист будет выгружаться в самостоятельный файл.
Neufazendnik, При всем своем уважении к RAR и Рошалам, много лет им не пользуюсь. Уже все ключи забыл. Портативная ругается что архив не архив :-(
Ну если 7zip или что-либо умеющее извлечь содержимое отсутствует, то кроме как копирования листа в новую книгу, записи и извлечения размера файла, который относительно скажет о размере информации вариантов у меня в голове нет.
Neufazendnik, Чем же вам так 7zip не угодил? :-) . Про ZIP не знаю, но кто мешает вам попробовать? Но в целом странно, что через GUI WinRAR не испытывает сложностей , а консольный уже пасует перед разрешением.
Да он не то, чтобы не угодил. Просто его нет на компе. Прежде чем устанавливать, хочу убедиться, что далее не вылезет эта проблема. И это не для случая этой темы, а так уже, ради спортивного интереса. Если моя программка при переносе на другой комп начнет требовать установки еще дополнительных приложений или прописывания путей на них, то это уже безобразие. Нужно таких решений избегать. Да, и еще. По моему уж проще получается сохранить лист в файл и запросить в явной форме размер файла