Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Excel VBA (часть 3)

Автор: ZlydenGL
Дата сообщения: 13.07.2010 16:27
Booklet, а как ругается-то? Какое сообщение? На MS Excel 2k3 работает влет просто.
Автор: Booklet
Дата сообщения: 13.07.2010 16:53
Ну... В процессе выполнения что-то там бурчит и предлагает STOP или DEBUG.
Если DEBUG - на эту строку отправляет.

Пришёл начальник и учит "как правильно делать". Сделал колонку с "сегодня", сделал колонку с 1 или 0 в зависимости от "больше ли дата". Улыбаюсь про себя.
Автор: ZlydenGL
Дата сообщения: 13.07.2010 17:01
Попробуй тогда строку

Код: Select Case DateDiff("d", Cells(I, 2), Now())
Автор: Booklet
Дата сообщения: 14.07.2010 10:23
Сделал по-детски

Код: Range("J2").Select
ActiveCell.FormulaR1C1 = "=TODAY()"

' собсна раскраска...
Cells.FormatConditions.Delete
Range("A2:G200").Select
Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=$G2<$J$2"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.Color = 255
End With
Автор: ZlydenGL
Дата сообщения: 14.07.2010 12:45
Ну тогда уж вот так сделать:

Код: Cells.FormatConditions.Delete
UsedRange.Select
Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=and($G2<TODAY();$G2<>"""")"
'Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.Color = 255
End With
Автор: Booklet
Дата сообщения: 14.07.2010 14:23
Увы,

Не проходит.

Добавлено:
Увы,

Не проходит.

Добавлено:
Ругается на
UsedRange.Select


Добавлено:
Вообще лично у меня конструкции типа "$G2<(TODAY()" не проходят - именно из-за этого мне пришлось выносить отдельно TODAY.
Автор: se111
Дата сообщения: 14.07.2010 19:13
Столкнулся с такой ситуацией,
необходимо вставить обьект(файл) word, excel или что либо еще
на определенный лист и потом сделать так чтобы вставленный обьект
нельзя было изменить.

вставляю документ так:

Private Sub CommandButton1_Click()
Worksheets("Document").Activate
Worksheets("Document").Range("C5").Activate
ActiveCell.BorderAround
Dim vFile As Variant
vFile = Application.GetOpenFilename("All Files,*.*", Title:=" Find file to insert")
If LCase(vFile) = "false" Then Exit Sub
ActiveSheet.OLEObjects.Add(Filename:=vFile, Link:=False, _
DisplayAsIcon:=True, IconFileName:="winword.exe", IconIndex:=0, _
IconLabel:=holdvar).Select

End Sub

ячейку можно защитить но она(вложенный документ) тогда не открывается вообще.
а нужно чтобы читать его можно было, а редактировать нет.
Ни у кого нет идей как такое сделать?




Добавлено:
если бы можно было как нибудь получить размер(килобайты, мегабайты) вложеннного оьекта, сравнить их и не сохранять например. Но как это
сделать дотумкать не могу.
Автор: dneprcomp
Дата сообщения: 14.07.2010 20:11
se111
Раз можно открыть, значит можно и изменить.
Делай копию документа и открывай уже ее. Пусть меняют. По закрытии просто delete копию.
Автор: se111
Дата сообщения: 15.07.2010 06:10
dneprcomp
а как это сделать ? я вообще плохо себе представляю как обращаться к внедренному
объекту. тем более его копировать.
нет каких нибудь примеров?

Автор: dneprcomp
Дата сообщения: 15.07.2010 08:12
se111
Вот один из возможных сценариев.
Не внедряй сразу в лист, а просто храни полный путь и имя файла. Можешь даже иконку поставить для наглядности. Для Word-a вордовскую, для Excel - экселевскую и т.д. На клик по иконке делаешь временную копию файла и уже ее открываешь. По закрытию можешь копию убить.

File and Folder Procedures in VBA Visual Basic for Applications
Basic file and folder examples using VBA in Microsoft Excel

vba file copy
Автор: Alexikit
Дата сообщения: 16.07.2010 07:45
подскажите пожалуйста, в обычном VB прекрасно работает код


Код: aaa= App.Path
Автор: ZlydenGL
Дата сообщения: 18.07.2010 11:22
Alexikit, на всякий случай лучше ссылаться на ThisWorkbook.Path. Например - если нужно получить этот самый путь в тот момент, когда на переднем плане находится другая книга (пользователь случайно переключил или макрос для обработки его открыл - без разницы), то ActiveWorkbook.Path вернет путь к этой самой книге "наверху", а не путь к макрососодержащей книге.
Автор: surgutfred
Дата сообщения: 19.07.2010 10:28
Спецы, а подскажите плиз такую вещь. Можно как то вызывать определенный макрос в любой книге? А то я понял что в существующей книге надо макрос прописывать. Или из другой книги макросом подгружать и обрабатывать.
Суть в чем - просто экспортром из сторонней программы получается книга excel, и хотелось бы ее сразу доработать. Т.е. Экспорт - открывается книга, жмем кнопочку макрос он работает.
???
Автор: Drazhar
Дата сообщения: 19.07.2010 10:39
surgutfred
Можно, если прописать этот макрос например в персоналдьную книгу ( personal.xls)

Добавлено:
Доброе время суток.
Ни разу не сталкивался
Есть задача - сукачать файл с корпоративного портала. Проблема - там стоит какая-то хитрая аутентификация на проксю. Решение с забитыми настройками логин-пароль применять нельзя.
пробовал через Set objHttp = CreateObject("MSXML2.ServerXMLHTTP") - н не выдает никак окошка с запросом пароля - хоть ты тресни, хотя при работе через ьбраузер(IE, Chrome - запросы есть).
Не сталкивался ли кто-нить с подобной задачей?
Заранее спс
Автор: Alexikit
Дата сообщения: 19.07.2010 11:00
ZlydenGL
Спасибо, учту.
Автор: KolyaP
Дата сообщения: 21.07.2010 13:31
Есть такой метод Find

Например
Set a = Worksheets(1).Range("a1:a500").Find(2, lookat:=xlWhole)

При исполнении этого примера сохраняется параметр lookat.

В следующий раз если в ручном режиме вызвать команду "Найти", будет установлен флажок "Ячейка целиком".
Есть ли способ прочитать этот параметр (lookat) и установить его желательно не вызывая метод Find?
Автор: ZlydenGL
Дата сообщения: 21.07.2010 14:24
KolyaP, можно задачу поиска "вынести" в переменную xls as Excel.Application, в этом случае ИМХО настройки поиска для текущего приложения не собьются. Правда это сразу означает общее замедление работы макроса (поскольку общение с переменной через COM пойдет).
Автор: KolyaP
Дата сообщения: 21.07.2010 15:13
ZlydenGL

Прошу прощения. Можно поподробнее?
Ничего не понял. Как это делается?

А можно непосредственно читать и устанавливать эту переменную(lookat)?
Автор: ZlydenGL
Дата сообщения: 22.07.2010 09:27
KolyaP, может быть и можно, да только я пока такого способа не нашел.

А делается предложенное мной так (на примере поиска файла в другой книге):

Код: Dim xls As Excel.Application, FindRes as Range
Set xls = CreateObject("Excel.Application")
' Открываем нужную книгу, в которой будем производить поиск, в режиме "только чтение" - чтоб не мешать другим процессам. Если по результатам поиска надо что-то исправлять в той же самой книге - последний False убираем
xls.Workbooks.Open FileName, False, False
' В этой книге на первом попавшемся листе ищем то, что нам надо
Set FindRes = xls.ActiveSheet.Cells.Find(FindString, lookat:=xlWhole)
' Дальше что-то делаем с найденышем
...
' Закрываем открытую книгу БЕЗ сохранения (если нужно сохранение, вместо False пишем True)
xls.ActiveWorkbook.Close False
' Закрываем переменную и освобождаем память
xls.Quit
Set xls = Nothing
Автор: KolyaP
Дата сообщения: 22.07.2010 10:19
ZlydenGL
Спасибо!
Попробую ради интереса, но как Вы верно заметили, врядли это разумно с практической точки зрения.

Насчет lookat, все обыскал, нигде не нашел способа ее чтения и независимой установки от процедуры Find. Скорее всего в Microsoft не предусмотрели никаких способов это сделать. Наверное это невозможно.
Автор: ZlydenGL
Дата сообщения: 22.07.2010 10:28

Цитата:
врядли это разумно с практической точки зрения.

На самом деле это неразумно только при массовых расчетах, например если есть процедура, обсчитывающая сразу несколько листов и хитро аггрегирующая данные на одном из. В таком случае падение производительности может достигать 50% (т.е. то, что в рамках одной книги считается 1 минуту, при использовании COM интерфейса считается полторы, да и то лавина времени уходит на создание процесса), да и то - если нужно для удобства пользователя сохранить нетронутыми какие-либо настройки, проще все-таки подождать чуть больше при обработке, но не затронуть пользовательские галочки. ИМХО
Автор: surgutfred
Дата сообщения: 22.07.2010 11:05
Drazhar

Цитата:
Можно, если прописать этот макрос например в персональную книгу ( personal.xls)

Если открываю книгу с диска, то да - в списке макросов есть PERSONAL.XLSB!macros, но если экспорт из сторонней программы - файл personal.xls не цепляется. Offiсe 2007
Автор: DmitryPrint
Дата сообщения: 22.07.2010 12:43
surgutfred

Цитата:
Можно как то вызывать определенный макрос в любой книге?
Сохранить файл с макросом как надстройку (файл с расширением *.xla). Затем подключить ее через Сервис > Надстройки.
Запуск:
Создать кнопку или новый пункт меню и назначить макрос (должен быть открыт любой файл) написав имя процедуры в соотв. меню. Функции можно использовать прямо на рабочем листе.
Автор: KolyaP
Дата сообщения: 22.07.2010 21:57
ZlydenGL

Попробовал Ваш метод. Действительно все работает и галочки в основном приложении не меняются. Даже удивительно, что можно запустить второй Excel и что-то им делать.

Но возникли некоторые но...

1. Как указано у Вас в коде нужно открывать заново файл. Соответственно он берется с диска, а если он уже открыт и изменен в первом Excel, но изменения не сохранены, то второй Excel эти изменения не увидит.

2.Запускается второй Excel достаточно медленно. Не пробовал сравнивать скорости первого и второго Excel когда второй открыт, но чтобы быстро работать очевидно надо заранее открыть второй Excel и все время держать его открытым.

3. Если я правильно посмотрел в Диспетчере задач, второй Excel занимает более 11МБ в оперативной памяти, что немало.

4. Наверняка усложнится отладка программ. Особенно как Вы указали, если второй Excel останется в памяти.

В общем я для себя пришел к выводу, что одна несохраненная галочка в интерфейсе пользователя не стоит того, чтобы задействовать этот способ. Есть другой способ решить задачу:

For j = 1 To N
If ra.Cells(j, 1) = to_find Then Exit For
Next j

но он на порядок медленнее, чем метод Find.

По моему лучше задействовать его, если очень нужно сохранить настройки пользователя.
Автор: ZlydenGL
Дата сообщения: 23.07.2010 07:59

Цитата:
Соответственно он берется с диска, а если он уже открыт и изменен в первом Excel, но изменения не сохранены

Фигня вопрос!

Код: Dim...
Thisworkbook.Save
Set xls =...
Автор: surgutfred
Дата сообщения: 23.07.2010 11:43
Продолжаю задавать вопросы
Тот же экспорт из сторонней программы. В файле некая таблица, но в зависимости от исходных данных кол-во столбцов и строк каждый раз разное, шапка таблицы то же скачет. Мне надо "привязаться" к таблице. Лучший вариант найти адрес последней ячейки шапки таблицы. Содержание этой ячейки я знаю. Как найти адрес ячейки, зная ее содержание? Содержание - текст. Осложнение еще в том что ячейка объединенная, и текст в ней не слева направо, а боком снизу вверх.
Как вариант, под шапкой идет строка с нумерованными столбцами, может ее найти и привязаться проще наверно будет?
Образец шапки
Автор: ZlydenGL
Дата сообщения: 23.07.2010 12:25
surgutfred, примерно так:

Код:
Dim C
' Ищем нужную ячейку, причем ищем содержимое ЦЕЛИКОМ!
C = Cells.Find("что-то-ищем", lookat:=xlWhole)
LastRow = C.Row
' Проверяем, не объединена ли данная ячейка; если объединена - добавляем число объединенных колонок
If C.MergeCells Then LastRow = LastRow + C.MergeArea.Rows.Count
Автор: Hugo121
Дата сообщения: 23.07.2010 21:26
Код типа
For j = 1 To N
If ra.Cells(j, 1) = to_find Then Exit For
Next j
будет ничуть не медленнее find, а вернее даже быстрее, если сперва загрузить диапазон в массив и перебирать его.

Например, такой код по выборке из диапазона отбирает 34000 значений на другой лист менее чем за секунду, причём меняя столбцы местами:


Код: Dim a(), b()
Sheets("999").Select
a = Range("l1:r65535")
ReDim b(1 To 65535, 1 To 7)

For i = 1 To 65535
If a(i, 7) <> 0 Then
k = k + 1
b(k, 1) = a(i, 7)
b(k, 2) = a(i, 1)
b(k, 3) = a(i, 4)
b(k, 4) = a(i, 5)
b(k, 5) = a(i, 6)
b(k, 6) = a(i, 3)
b(k, 7) = a(i, 2)
End If
Next

Sheets("777").Cells(5, 1).Resize(k, 7) = b
Автор: ZlydenGL
Дата сообщения: 23.07.2010 23:35
Hugo121, ну тогда держи пополнение статистики - в MS Excel 2k3 скорость перебора через .Find ВСЕГДА быстрее перебора в цикле For, что бы при этом не перебиралось - ячейки листа или ячейки массива. Проверял неоднократно в течение многих лет с разными вариантами При небольших значениях массива поиска еще удавалось хоть как-то сравнять счет, но вот если искать приходилось несколько раз, да по двухмерному массиву, да с переходом вперед-назад... Не, альтернативе .Find под MS Excel 2k3 я лично не знаю Вот если размерность массива 3 и больше - тогда альтернативы For нет, но пока размерность массива 1 или 2 - живем
Автор: Hugo121
Дата сообщения: 24.07.2010 15:29
ZlydenGL
Да, проверил - немного Find выигрывает - до 3 сотых секунды, если значение ToFindThis в R35699 (т.е. примерно в середине листа), и значительно (практически время 0), если найденное в начале диапазона. Но общее время менее секунды в обоих вариантах, т.е. практически одинаковое.
У массива время примерно одинаковое в обоих случаях, хоть и стоит выход из цикла при нахождении. Т.е. больше времени занимает организация процесса, чем сам перебор.
Для чистоты эксперимента была одинаково навешана перестановка в найденном ряду данных местами и выгрузка в другой лист.
Это если надо найти 1 значение. А вот если надо отобрать по 7 значений из 17853 рядов, где найдена единица? Через FindNext это заняло в 15 раз больше времени (по 3 попытки):

FindFindArrStatus 15,21875
FindFindArrStatus 15,39063
FindFindArrStatus 15,17188
FindArrStatus 0,796875
FindArrStatus 0,796875
FindArrStatus 0,796875

Причём я найденное заносил в массив (в обоих вариантах), и затем выгружал на лист всё сразу. Если выгружать каждое найденное значение по одному, не используя массив... не хочу даже пробовать.
Причём с FindNext ещё морока с первым и последним найденным значением, в этом коде не исправлял.
Да и код с FindNext организовать посложнее, чем простой цикл перебора массива.

Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127

Предыдущая тема: VS 2010


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.