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

» Excel VBA (часть 3)

Автор: oshizelly
Дата сообщения: 04.07.2010 10:15
В соседнем топике уважаемый мембер jurris 03-07-2010 14:14 дал ссылку на опубликованный в другом форуме код. Назначение макроса: переместить фокус ввода к ячейке, которая редактировалась (или была текущей?) предпоследней (аналог хоткея Shift+F5 в MS Word).
[more=код макроса]Private Sub Workbook_Open()
Set rPenultimate = ActiveCell
Set rPrevious = rPenultimate
Set rCurrent = rPenultimate
End Sub

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
UpdatePenultimate
End Sub

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, _
ByVal Target As Excel.Range)
UpdatePenultimate
End Sub

Regular code module:

Public rCurrent As Range
Public rPenultimate As Range
Public rPrevious As Range

Public Sub UpdatePenultimate()
Set rPenultimate = rPrevious
Set rPrevious = rCurrent
Set rCurrent = ActiveCell
End Sub

Public Sub GoToPenultimate()
If Not rPenultimate Is Nothing Then Application.GoTo rPenultimate
End Sub[/more]

Однако после вставки готового кода в окно VBA после каждого блока, завершающегося строкой End Sub, появлятся линейка - разделитель макросов (что, наверное, и логично), а в выпадающем списке макросов вверху окна каждый из блоков этого макроса рассматривается как отдельный макрос. А строка Regular code module: вообще показана красным. Пробовал убрать пустые строки между блоками, но это не помогло.
Подскажите, в чём тут хитрость?

И, кстати, можно ли увеличить число запомненных предыдущих позиций фокуса, скажем, до 5 (этот макрос, как я понимаю, помнит всего две предыдущих позиции)

Спасибо!

Автор: Tambourine
Дата сообщения: 04.07.2010 10:54
Hugo121

Цитата:
Победил жирность!

Вы просто умничка, спасибо Вам огромное! Макрос удалось запустить, все прекрасно работает. Мое предложение остается в силе, скиньте реквизиты в личку или сюда.
Автор: Hugo121
Дата сообщения: 04.07.2010 12:15
Tambourine
Проверьте почту из профиля, я там и аттачмент приложил, на всякий случай. Ещё вчера.
Если надо переделать макрос на обработку разных файлов (список в одном, комменты в другом) - пишите на почту, доделаю.

Добавлено:
oshizelly
Всё, что после Regular code module, надо писать в модуль.
То, где Workbook - в модуль книги.
То, где Worksheet - в модуль листа (здесь такого нет)
Автор: oshizelly
Дата сообщения: 06.07.2010 16:45
Подскажите, как решить задачу, а то уже последний остаток мозга сломал. Имеются два столбца с данными (вообще-то, две пары столбцов, но можно эту операцию разбить на два шага), данные в пределах строки в обоих столбцах, в основном, совпадают, но некоторые отличаются. Надо как-то выделить те строки, в которых данные в обоих столбцах не совпадают (ну, или наоборот, в которых совпадают).

Для чисто числовых данных и для дат нашёл решение, лежащее на поверхности: в третьем столбце написал формулу =A1-B1, для совпадающих данных ответ, ясно, 0, для несовпадающих - отличный от нуля. Примитивное, но решение. Однако таким образом невозможно сравнить данные:
- имеющие текстовый формат;
- содержащие разные по тексту комментарии (или, как минимум, надо хотя бы отметить различия между ячейками, содержащими и не содержащими комментарии).
- содержащие формулы (ячейка с формулой =1+1 считается идентичной ячейке с формулой =8/4, а это неверно);

Насколько я понял, стандартными средствами Excel эта задача вообще не решается. А при помощи VBA?

Заранее спасибо!

P.S.
А ещё хорошо бы несовпадающие строки подсветить цветной заливкой.
Автор: vlth
Дата сообщения: 07.07.2010 00:19
oshizelly

Цитата:
Подскажите, как решить задачу, а то уже последний остаток мозга сломал. Имеются два столбца с данными (вообще-то, две пары столбцов, но можно эту операцию разбить на два шага), данные в пределах строки в обоих столбцах, в основном, совпадают, но некоторые отличаются. Надо как-то выделить те строки, в которых данные в обоих столбцах не совпадают (ну, или наоборот, в которых совпадают).

Для чисто числовых данных и для дат нашёл решение, лежащее на поверхности: в третьем столбце написал формулу =A1-B1, для совпадающих данных ответ, ясно, 0, для несовпадающих - отличный от нуля. Примитивное, но решение.


Формула условного форматирования: =A1<>B1

Для остального - да, надо VBA подключать.
Автор: oshizelly
Дата сообщения: 07.07.2010 02:14
vlth

Цитата:
Формула условного форматирования: =A1<>B1

Но это годится только для ячеек с числовым значением. А для текста нет ничего похожего? Операция-то ведь совершенно стандартная, вряд ли я первый, кому понадобилось сравнить два набора данных.
Автор: Hugo121
Дата сообщения: 07.07.2010 10:43
Почему же? Текст тоже можно сравнивать этой формулой.
Автор: oshizelly
Дата сообщения: 07.07.2010 11:15
Hugo121

Извиняюсь, не туда посмотрел. Но это решение через условное форматирование. А нет ли решения по тому алгоритму, что я уже предложил для чисел: проверить тождественность значений соседних ячеек и выдать ответ в третьем столбце?
именно

А по поводу сравнения комментариев нет никаких идей, хотя бы в бинарном режиме "есть/нет".
Опять-таки это ведь не слишком оригинальная задача, вроде бы должны существовать стандартные решения.
Автор: Hugo121
Дата сообщения: 07.07.2010 13:56
Сравнить комменты макросом:

Код: Sub tt()
If Cells(1, 1).Comment.Text = Cells(1, 2).Comment.Text Then MsgBox "OK"
End Sub
Автор: teleset
Дата сообщения: 08.07.2010 11:07
Есть файлы определеной структуры.
Данные в этом файле сгрупированны.
необходимо автоматизировать выгрузку а текстовый файл, одним из параметров которого является НАЗВАНИЕ ГРУПП.
Необходимо определить начало группы (название), затем обработать данные после этого названия до начала следующей группы.
Автор: Hugo121
Дата сообщения: 08.07.2010 11:14
teleset - подробнее опишите, и пример нужен, иначе корректного кода не дождётесь.
Автор: Booklet
Дата сообщения: 12.07.2010 12:36
Подскажите, плиз.
Вот есть у меня список типа:
Маша | 26.05.2010 17:40:58
Аня | 26.05.2010 17:40:58
Валдис | 26.05.2010 17:40:58

В итоге мне нужен раскрашенный список типа
Маша 26,05,10
Аня 26,05,10
...и т.д.

0. Как преобразовать формат - понятно, это сделано.

1. Но мне надо раскрасить.
Это самое "26.05.2010 17:40:58" надо сравнивать с текущей датой (можно и временем, но непринципиально) и всю строку (точнее, несколько столбцов) красить в, например, красный если эта самая дата меньше текущей.

2. можно чуть усложнить, - если разница более N, то цвет, напримеР, розовый.

3. А ещё в табличке есть внизу мусор.
Надо в столбце "А" искать текст "вот_такой_текст" и удалять всё, что ниже (включая сам текст)
Автор: ZlydenGL
Дата сообщения: 12.07.2010 13:01
Чистая раскраска ячеек с датами может быть сделана через Conditional Formatting (Условное Форматирование на русском, если не ошибаюсь). Вот если нужно закрашивать всю строку (или несколько столбцов строки) - тогда уже придется код подключать.

Для сравнения можно использовать формулу "=Now()" (как на русском звучит - не знаю, но должно быть что-то элементарное), соответственно "вчера" считается как "=Now() - 1", "завтра" - "=Now() + 1" и т.д.

Удаление можно делать автофильтром и руками в принципе.

Ну а если задача такова, что VBA нужно ОБЯЗАТЕЛЬНО использовать - свистни, набросаем алгоритм Принцип рисования можно посмотреть, включив запись макроса, а затем произведя непосредственно раскраску.
Автор: Booklet
Дата сообщения: 12.07.2010 13:27
обязательно.
"Запись макроса" пробовал, но как-то нифига. ПроблемА, как понимаю, ещё и в том, что функции в скрипт не вписать.
Кстати, я прав что макрос это и есть "Excel VBA"?

Руками ничего низзя, так как это отчёт, который должна делать секретарша.

Добавлено:
Кажется, NOW по-русски так и будет, т.е. СЕЙЧАС
Автор: ZlydenGL
Дата сообщения: 12.07.2010 14:01
Да, макрос - это программная инструкция на Excel VBA.

Йэх... Если нужен именно VBA, то тогда получится примерно следующее:


Код: Dim I as Long
For I = Cells.SpecialCells(xlLastCell).Row DownTo 2 ' Предполагаю, что в строке 1 находится шапка, ее смотреть смысла нет
If Cells(I, 1) = "вот_такой_текст" Then
Rows(I).Delete
Else
Select Case datediff("d", Cells(I, 2), Now())
Case 0 ' Дата в ячейке - сегодня
Rows(I).Interior.ColorIndex = 4 ' ПОДОБРАТЬ!!!
Case 1 ' Дата в ячейке - вчера
Rows(I).Interior.ColorIndex = 5 ' ПОДОБРАТЬ!!!
Case 2 ' Дата в ячейке - позавчера
Rows(I).Interior.ColorIndex = 6 ' ПОДОБРАТЬ!!!
End Select
End If
Next I
Автор: Booklet
Дата сообщения: 12.07.2010 14:27
Не пробовал, но у меня сложилось впечатление, что будет удалена только строка с "вот_такой_текст".

Подобрать надо цвет? Тогда понятно.

А вот как работает case я не понял.
Что такое "d"?
+ у меня сложилось впечатление, что краситься тоже будет только ячейка
Автор: ZlydenGL
Дата сообщения: 12.07.2010 15:10

Цитата:
у меня сложилось впечатление, что будет удалена только строка с "вот_такой_текст".

Ага, это я для простоты написал, предполагая, что ВЕСЬ лишний массив будет помечен в столбце А при помощи шаблона "вот_такой_текст". Если действительно нужно тупое удаление всего, что ниже первого попавшегося "вот_такой_текст" - код будет немножко иным.


Цитата:
Подобрать надо цвет?

Не цвет, а ColorIndex цвета Проще всего подбирать при помощи записи макроса и последущего раскрашивания различными цветами ячеек.


Цитата:
как работает case я не понял

Результат отработки оператора Select Case сравнивается со значениями Case, идущими ниже. С чем результат совпадет - тот набор команд и будет выполнен. Подробнее - в справке по VBA.


Цитата:
Что такое "d"?

Ищем разницу в днях.


Цитата:
краситься тоже будет только ячейка

Не, закрашиваться будет ВСЯ строка, начиная от столбца А - и еще 255 столбцов вправо

Добавлено:
Вот кстати хорошая картинка с msdn - перечисление базовых индексов цвета:
Автор: Booklet
Дата сообщения: 12.07.2010 15:21

Цитата:
ниже первого попавшегося "вот_такой_текст" - код будет немножко иным.

оно и надо

Цитата:
Не цвет, а ColorIndex цвета
Ну, это я и подразумевал


Цитата:
Результат отработки оператора Select Case сравнивается со значениями Case, идущими ниже.

Прочитал, не доходит.
Что такое d?
Это стандартный атрибут Case?
Смысл понятен, а вот как работает - нет. Вижу, что разницу считает. Кстати, а операторы сравнения можно?
Автор: ZlydenGL
Дата сообщения: 12.07.2010 15:39
Допетрил Ты не разграничиваешь 2 различных функциональных оператора:
1. Оператор условного перехода Select Case .... End Select
2. Оператор вычисления разницы между датами DateDiff()

Естественно всю конструкцию можно переписать так:

Код: If datediff("d", Cells(I, 2), Now()) = 0 Then ' Дата в ячейке - сегодня
Rows(I).Interior.ColorIndex = 4 ' ПОДОБРАТЬ!!!
If datediff("d", Cells(I, 2), Now()) = 1 Then ' Дата в ячейке - вчера
Rows(I).Interior.ColorIndex = 5 ' ПОДОБРАТЬ!!!
If datediff("d", Cells(I, 2), Now()) = 2 ' Дата в ячейке - позавчера
Rows(I).Interior.ColorIndex = 6 ' ПОДОБРАТЬ!!!
End If
Автор: Booklet
Дата сообщения: 12.07.2010 15:45
Ясно. Спасибо, бум думать.
Автор: ZlydenGL
Дата сообщения: 12.07.2010 15:46
В общем вот что у меня получилось:


Код: Dim I as Long, Found as Object
' Ищем шаблон, после которого все удалить нужно нафиг
Set Found = Cells.Find("вот_такой_текст", lookAt:=xlWhole)
If Not TypeName(Found) = "Nothing" Then ' Можно заменить конструкцией If Not Found Is Nothing Then
' Точка входа найдена, удаляем
Rows(Found.Row & ":" & Cells.SpecialCells(xlLastCell).Row).Delete
End If
For I = 2 To Found.Row - 1 ' Предполагаю, что в строке 1 находится шапка, ее смотреть смысла нет
Select Case datediff("d", Cells(I, 2), Now())
Case 0 ' Дата в ячейке - сегодня
Rows(I).Interior.ColorIndex = 4 ' ПОДОБРАТЬ!!!
Case 1 ' Дата в ячейке - вчера
Rows(I).Interior.ColorIndex = 5 ' ПОДОБРАТЬ!!!
Case 2 ' Дата в ячейке - позавчера
Rows(I).Interior.ColorIndex = 6 ' ПОДОБРАТЬ!!!
End Select
Next I
Автор: Booklet
Дата сообщения: 13.07.2010 09:37
Мэа... Как-то не пашет...
Ну, во-первых макрос будет храниться в "личной книге макросов". Это важно, так как файл, над которым макрос трудится одноразовый. Просто типовой.

Кроме того, - видимо, я неправ. "вот_такой_текст" это часть содержимого ячейки. То есть рано или поздно в столбце А попадётся ячейка, в которой содержимое начинается с этого текста.
Автор: ZlydenGL
Дата сообщения: 13.07.2010 12:11
ОК, личная книга - так личная книга. А запускаться как будет?

Добавлено:
Неправильно выразился, пардон: как планируешь запускать этот макрос? Или как его будет запускать отвественный человек (секретарь)?
Автор: Booklet
Дата сообщения: 13.07.2010 12:35
Либо тычками "вид-макрос" либо кнопочку сделаю
Автор: ZlydenGL
Дата сообщения: 13.07.2010 13:22

Цитата:
Либо тычками "вид-макрос"

Наверное все-таки Alt+F8?


Цитата:
кнопочку сделаю

Ага, значит такие знания есть Уже проще!

Теперь возвращаемся в начало:

Цитата:
Как-то не пашет...

Что не пашет? Не рисует вообще ничего? Трейсинг что показывает - вход в процедуру задачи ColorIndex'а вообще производится?
Автор: Booklet
Дата сообщения: 13.07.2010 13:36

Цитата:
Наверное все-таки Alt+F8?

Не. У неё на сочетания клавиш аллергия. Вот мышкой подвигать - это пожалуйста.
Кстати, в процессе творчества у меня много лишних модулей остаётся - как их убрать?

Не рисует ничего. Ругается на строку с комментарием про "строку 1 не смотрим"

Вообще я пытаюсь с другого боку зайти.

Код: Cells.FormatConditions.Delete
Range("A2:G900").Select
Dim Y As Long
Y = Now()
Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=$G2>Y"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 6737151
.TintAndShade = 0
End With
Автор: ZlydenGL
Дата сообщения: 13.07.2010 13:56

Цитата:
Вообще я пытаюсь с другого боку зайти.

Стоп-стоп! Условное форматирование обрабатывает только ОДНУ ячейку, ТЕКУЩУЮ! Т.е. если такое же условное форматирование применить не к дате, а к числовой/строковой таблице, эффект будет нулевым. Так что лучше все-таки красить через Rows().Interior.ColorIndex. Хотя могу ошибаться - попробую обязательно.

А проблема элементарная, напиши в формуле "=$G2>Now()" - переменные в функцию рабочего листа MS Excel не передаются.

Добавлено:
А, режим разметки по формуле, а не по ячейке. Интересная мысль, только с адресами полная путаница Щас пошаманю

Добавлено:
Так, доперло. Условное форматирование по формуле работает так: формула возвращает хоть что-то помимо нуля или пустоты - закрашиваем, иначе - фиг. Т.е. нужно вбивать следующую формулу для заливки строки за вчерашний день:

Код: =if(trunc(now()-$G2)=1;1;0)
Автор: Booklet
Дата сообщения: 13.07.2010 14:12

Цитата:
Так что все равно закрашивать через Rows() придется

Наверное.
У меня в прошлый раз было проще, так как сравнивать надо было не дату и "сегодня", а дату и дату.
Автор: ZlydenGL
Дата сообщения: 13.07.2010 14:26
Ага, понял, где со своим кодом тупанул. Все просто - если "вот_такой_текст" не встречается ни разу - объект Found оказывается пустым. Модифицируем, получаем [more=это]
Код: Dim I As Long, Found As Range
With ActiveSheet
' Очищаем все выделения цветом на странице
.Cells.Interior.ColorIndex = -4142
' Ищем шаблон, после которого все удалить нужно нафиг
Set Found = .Cells.Find("вот_такой_текст", lookAt:=xlWhole)
If Not TypeName(Found) = "Nothing" Then ' Можно заменить конструкцией If Not Found Is Nothing Then
' Точка входа найдена, удаляем
.Rows(Found.Row & ":" & .Cells.SpecialCells(xlLastCell).Row).Delete
Else
' Иначе просто запоминаем последнюю на листе ячейку
Set Found = .Cells.SpecialCells(xlCellTypeLastCell)
End If
For I = 2 To Found.Row - 1 ' Предполагаю, что в строке 1 находится шапка, ее смотреть смысла нет
Select Case DateDiff("d", Cells(I, 2), Now())
Case 0 ' Дата в ячейке - сегодня
.Rows(I).Interior.ColorIndex = 4 ' ПОДОБРАТЬ!!!
Case 1 ' Дата в ячейке - вчера
.Rows(I).Interior.ColorIndex = 5 ' ПОДОБРАТЬ!!!
Case 2 ' Дата в ячейке - позавчера
.Rows(I).Interior.ColorIndex = 6 ' ПОДОБРАТЬ!!!
End Select
Next I
End With
Автор: Booklet
Дата сообщения: 13.07.2010 15:54
Теперь ругается на
Select Case DateDiff("d", Cells(I, 2), Now())

Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127

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


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