Модераторы: mihanik
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обработка события DocumentBeforeClose в Word 
:(
    Опции темы
McConst
Дата 29.11.2013, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 29.11.2013

Репутация: нет
Всего: нет



Здравствуйте.
В Normal.dot имеется следующий обработчик закрытия документов, который отправляет закрываемый файл на e-mail

Код

Private WithEvents objWordApp As Word.Application
Public Terminate As Boolean ' Флаг ничего не отправлять на е-маил, если на форме нажата кнопка "отмена"

Private Sub Document_Open()
'Событие на открытие очередного файла word
    Set objWordApp = Word.Application
End Sub

Private Sub objWordApp_DocumentBeforeClose(ByVal doc As Document, Cancel As Boolean)
        Terminate = False
        UserForm1.Show 'Заполняем получателя хим. анализа
        If Terminate Then Exit Sub
        Call EMAS.EMAS(doc)' Процедура отправки документа на е-маил
End Sub


Столкнулся с такой проблемой. Если одновременно открыто несколько документов (допустим - 4), и одно из окон закрываем, то для закрываемого документа это событие вызывается столько же раз (тоже 4). И соответственно на е-маил приходит 4 копии одного и того же документа. Не могу придумать как устранить эту проблему?
PM MAIL WWW ICQ Skype   Вверх
Akina
Дата 29.11.2013, 23:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 26
Всего: 454



Static флаг.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
McConst
Дата 29.11.2013, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 29.11.2013

Репутация: нет
Всего: нет



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

Вообще мне здесь не понятно следующее. Я так понимаю, что для закрытия одного файла событие beforeClose должно вызываться один раз, независимо от того, какие ещё окна word открыты. А оно вызывается для одного и того же файла (входящие аргументы не меняются) по нескольку раз. Может я неправильно задал в Normal.dot обработчик создания событий? Вроде бы правильно.
PM MAIL WWW ICQ Skype   Вверх
McConst
Дата 30.11.2013, 00:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 29.11.2013

Репутация: нет
Всего: нет



Попробовал такой вариант обработчика события

Код

Private Sub objWordApp_DocumentBeforeClose(ByVal doc As Document, Cancel As Boolean)
'Обработчик закрытия документа.

'Если открыто одновременно много окон, процедура для одного документа вызывается много раз, поэтому нужно
'Вводить флаги Static, чтобы отправка на е-маил была однократной

Static closedDoc As Document ' Указатель на документ, который уже надо бы закрыть, а он не закрыт
Static Repeated As Boolean ' Проверяет, выполняется ли процедура повторно

If (closedDoc = Nothing) Then
    Repeated = False
End If
    If Not Repeated Then
        Terminate = False
        UserForm1.Show 'Заполняем получателя слитка
        If Terminate Then Exit Sub
        Call EMAS.EMAS(doc)
        Set closedDoc = doc
        Repeated = True
    End If
End Sub


Мысль такая, что если обработчик вызывает не старый документ повторно, а новый, тогда static будет всегда nothing, так как указатель на документ после закрытия должен вроде бы как пропадать или быть некорректным (nothing). Но компилятор выдает ошибку в 10-й строке. Можно было бы развить идею, но я пока в тупике.

PM MAIL WWW ICQ Skype   Вверх
Akina
Дата 30.11.2013, 09:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 26
Всего: 454



Ну флаг-то надо определять не на уровне приложения, а на уровне отслеживаемого объекта - в данном случае документа.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
McConst
Дата 30.11.2013, 14:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 29.11.2013

Репутация: нет
Всего: нет



Решил проблему, но пришлось повозиться. В обработчик DocumentBeforeClose передается аргумент doc, в котором есть уникальный параметр Doc.DocID Он лучше имени тем, что при повторном открытии документа этот параметр меняется и не будет ложного совпадения имен.

Так вот, этот параметр при очередном выполнении обработки события сравнивается с переменной типа Static DocID as long. Но тут есть ещё один нюанс. Переменную нельзя прописывать в ThisDocument в Normal.dot, так как при следующем вызове все изменения куда-то пропадают. Я так понимаю, если открыто много окон происходит вызов события на закрытие моего конкретного окна сразу во всех экземплярах открытых документов с передачей параметров моего документа. В общем, процедуру сравнения DocID с doc.DocID нужно проводить в отдельном модуле Normal.dot в виде отдельной функции сравнения.
Вот такой код у меня получился:

Код

Private WithEvents objWordApp As Word.Application


Private Sub Document_Open()
'Событие на открытие очередного файла word
    Set objWordApp = Word.Application
End Sub

Private Sub objWordApp_DocumentBeforeClose(ByVal doc As Document, Cancel As Boolean)
'Обработчик закрытия документа.

    If Not IsExecuted(doc.DocID) Then
        EMAS.Terminate = False
        UserForm1.Show 'Заполняем получателя е-маил
        If EMAS.Terminate Then Exit Sub' На форме нажата кнопка "отменить" отправку по е-маил
        Call EMAS.EMAS(doc)'Отправка по е-маил
        Call IsExecuted(doc.DocID, True)'Идет присваивание переменной нового DocID после отправки по е-маил
    End If
End Sub



И сама функция проверки и присваивания нового DocID  в моем модуле EMAS

Код

Public Function IsExecuted(ByVal doc As Long, Optional Setting As Boolean = False) As Boolean
'Функция сравнивает закрываемый документ с ранее закрытым
'Нужна для однократного выполнения обработчика события DocumentBeforeClose
Static DocID As Long

If Not Setting Then
  If DocID = doc Then
      IsExecuted = True
  Else
      IsExecuted = False
  End If
Else
    DocID = doc
End If
End Function

PM MAIL WWW ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Программирование, связанное с MS Office"
mihanik staruha

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами



  • Несанкционированная реклама на форуме запрещена
  • Пожалуйста, давайте своим темам осмысленный, информативный заголовок. Вопль "Помогите!" таковым не является.
  • Чем полнее и яснее Вы изложите проблему, тем быстрее мы её решим.
  • Оставляйте свои записи в "Книге отзывов о работе администрации"
  • А вот тут лежит FAQ нашего подраздела


Если Вам понравилась атмосфера форума, заходите к нам чаще!
С уважением mihanik и staruha.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Программирование, связанное с MS Office | Следующая тема »


 




[ Время генерации скрипта: 0.0519 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.