Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: обработчик событий формы/контрола

Доброго дня!
Мне необходимо в рантайме разным контролам и формам назначить идентичный обработчик события - некоторую пользовательскую функцию ОБРАБОТКА, определенную в общем модуле. Например, назначить ее событию OnMouseDown. С назначением обработчика в VBA нет вопросов: ="=ОБРАБОТКА()", но как передать параметры стандартного обработчика, которые есть в модуле формы при использовании "[event procedure]" - MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single).
Вопрос - как значения этих параметров передать в мою функцию ОБРАБОТКА(Button As Integer, Shift As Integer, X As Single, Y As Single)?

спасибо.
Ответ: v-e-t, добрый день.

Собственно, Predeclared уже все сказал, я лишь добавлю, пару слов. Может вам пригодится.
К параметрам, которые вас интересуют (Button As Integer, Shift As Integer, X As Single, Y As Single), можно получить доступ только из модуля формы. Делегаты тут не используешь. Писать код в каждой форме вас не устраивает, значит, как сказал Predeclared, на эти события нужно подписаться откуда-нибудь. Причем это должен быть только модуль класса.
Собственно я и хотел предложить вариант.
Вот тут я выкладывал файл:

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

Вы хотите в одном месте разместить код, который будут использовать разные формы/отчеты и их контролы. Т.е. нужен класс.

в примере, что я дал, одна из подсистем это своеобразный Диспетчер уровня приложения, который следит за происходящим: Открытие/Закрытие/Активация/Декативация форм/отчетов в приложении(Диспетчер представлен двумя классами и одним интерфейсом) и генерирует соответствующие события.

Так вот. По вашей задаче. Как я сказал, вам нужен класс, где вы разместите свой код на все случаи жизни.
В моем примере таким классом был модуль формы F_Start. В этом классе, создается объектная переменная типа Диспетчера.
Это вам дает доступ ко событиям Диспетчера. А события эти:
Event AfterOpenFR(FR_Object As Object)
Event ActivationFR(FR_Object As Object, blnAfterOpen As Boolean)
Event DeactivateFR(FR_Object As Object, intReasonDeact As ReasonDeact, NewFR As Object, FR_IsBeingActivated As Object)
Event CloseFR(FR_Object As Object)

Т.е. вы получаете возможность прослушивать из одного места события Открытие(суррогат этого события)/Закрытие/Активация/Декативация всех форм/отчетов. Непосредственная дальнейшая организация - это уже ваше творчество, как построите.

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

Прочитал тут на сайте Таурион про такое интересное событие формы, как "Уход с записи (RecordExit)". Вот цитата:

Уход с записи
Событие Уход с записи (RecordExit) происходит всякий раз, когда пользователь пытается выйти (переместить фокус) с текущей записи: перейти к другой записи, закрыть форму, обновить данные в форме и т. д. Процедура обработки этого события может использоваться для проверки корректности данных в текущей записи. Процедура имеет один параметр: cancel. Если установить его значение равным True, то можно запретить пользователю покидать текущую запись.
Насколько я потом нашел в инете, это событие убрали начиная с Акса 2002.

Заинтересовался им, поскольку мне кажется, что оно бы мне пригодилось в моем конкретном случае (хотя, само собой, скорее всего это можно решить иначе).

Суть задачи такая.

Есть табличная форма, основанная на запросе, в котором - две таблицы: основная (Таблица1) и связанная с ней "один ко многим" (Таблица2). И в данной форме необходимо дать пользователю возможность ДОБАВЛЯТЬ строки, т.е. при заполнении ОДНОЙ СТРОКИ будет происходить добавление данных В ОБЕ эти связанные таблицы.

Так вот, форма вполне логично не дает заполнять некоторые поля этой строки, пока не будет сохранена основная запись, т.е. юзер может ввести, допустим, два-три поля (которые физически находятся в Таблице1), а заполнить поля, которые физически находятся в Таблице2 - не может, пока не будет сохранена основная запись в Таблице1. Здесь все логично.

При этом есть поля, которые должны быть обязательно заполнены. Из них большинство - из Таблицы1, а пара штук - из связанной Таблицы2.

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

Поэтому хотел "разделить" проверку заполнения обязательных полей на два этапа: по событию формы "До обновления" - проверяем заполненность только полей из Таблицы1 (таким образом оно дает сохранить основную запись, не натыкаясь на проверку заполненности полей Таблицы2), а на событие "Уход с записи" - сделать проверку заполнения оставшихся обязательных полей Таблицы2, и таким образом не дать юзеру уйти с записи, если не заполнены и эти два обязательных поля.

И вот после такого "красивого" построения проверки я натыкаюсь на то, что такого события, как "Уход с записи" уже просто не существует))... Обидно.

Подскажите, пожалуйста, как можно еще решить эту задачку?.. Заранее спасибо за подсказки)
Ответ: mobile, Спасибо за развернутый ответ и мнение).
А по моей ситуации - да, посмотрел я на это безобразие, и понял, что лучше вообще убрать возможность добавлять и удалять строки непосредственно в этой табличной форме, оставил только возможность делать это с кнопки, которая вызывает отдельную форму. А то оно, оказывается, еще и чудило при удалении: если удалять прямо в этой форме, то оно вроде как удаляет, в форме уже не отображается, а на самом деле - удаляет только подчиненную запись, оставляя основную в Таблице1... Что интересно, даже событие "Удаление" на данной форме не происходит, что ли, поскольку пытался его поймать - и ни фига, ноль реакции. В итоге плюнул, пускай пользуются кнопками)...
Вопрос: Как изменить название формы, в режиме диалогового окна

Таким образом все прекрасно работает, название формы меняется:
Visual Basic
1
2
DoCmd.OpenForm "НоваяКвартира1", acNormal, "", "[КодНедвижимость]=" & Forms![ЗаявкиНаКвартиры]![КодНедвижимость], acEdit
Forms.НоваяКвартира1.Caption = "Квартира"
Но если добавляю то, что форма - диалоговое всплывающее окно, то выдает ошибку 438 и название формы не меняется. В чем может быть причина?
Visual Basic
1
2
DoCmd.OpenForm "НоваяКвартира1", acNormal, "", "[КодНедвижимость]=" & Forms![ЗаявкиНаКвартиры]![КодНедвижимость], acEdit, acDialog
Forms.НоваяКвартира1.Caption = "Квартира"
Ответ:
Сообщение от Jamaica
If Me.DataEntry Then Me.Caption = "New Record"
К сожалению, не получилось...
Сообщение от mobile
Диалоговая форма прекращает выполнение кода в вызывающей процедуре
Все верно, именно на этой строчке прекращает!, только не понятно почему, ведь если не диалоговая форма то выполнение продолжается дальше...
Сообщение от mobile
Me.Caption = Nz(Me.OpenArgs, Me.Caption)
Супер..., спасибо..)

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

Добавлено через 1 час 5 минут
На одной кнопке этот код срабатывает, а на другой передать имя "Новая квартира" я не могу, т.к. уже занято и передается Me.Name
Visual Basic
1
DoCmd.OpenForm "НоваяКвартира1", , , , acFormAdd, acDialog, Me.Name
Это нужно для данного кода на вставку:
Visual Basic
1
2
3
4
5
6
Private Sub Form_AfterInsert() 'Событие формы После вставки
    If CurrentProject.AllForms(Me.OpenArgs).IsLoaded = True Then
       Forms(Me.OpenArgs).[КодНедвижимость] = Me.[КодНедвижимость]
       Forms(Me.OpenArgs).[КодНедвижимость].Requery
    End If
End Sub
Указать явно название формы вместо Me.OpenArgs я не могу, поскольку:
Поэтому сделал так:
Visual Basic
1
2
3
4
5
6
Private Sub Form_Open(Cancel As Integer)
    Me.Caption = Nz(Me.OpenArgs, Me.Caption) 'принимаем название формы из формы ЗаявкиНаКвартиру
    If Me.Caption = "ЗаявкиНаКвартиру" Then
       Me.Caption = "Новая квартира"
    End If
End Sub
Вроде все нормально..)

Добавлено через 3 минуты
п.с. Слава богу нет третьей кнопки, иначе был бы тупик
Вопрос: Несрабатывает событие Click

Приветствую!
Не могу понять, почему не срабатывает процедура на событие "нажатие кнопки"

К сообщению приложен файл. Размер - 129Kb
Ответ: guest_rusimport,
Yess, заработал.
В коде обесточил 2 строки, связанные с Cancel. И заработало.
Если бы при отладке проблема возникала на том куске кода, я бы ...
Но отладка даже не то, что не доходила, она вообще никак не реагировала - не входила в процедуру.
Ничего не понял. (((
Спасибо большое



Private Sub KnCikis_Click()
Dim Vibor As Integer
    Vibor = MsgBox("Kayid edilsin mi?", vbYesNoCancel, "Cikis")
    If Vibor = vbYes Then
        DoCmd.Close
    ElseIf Vibor = vbNo Then
        Me.Undo
        If mblnInTrans Then
            mwks.Rollback
            mblnInTrans = False
            Me.Tarih.SetFocus
            Call ResetData
        End If
    'ElseIf Vibor = vbCancel Then
    '    Cancel = True
    End If
End Sub
Вопрос: Не сохраняется фон после закрытия формы VBA

Доброго времени суток.
После нажатия на надпись выполняется программа VBA сортировка и задает цвет фона, но после закрытия и открытия формы сортировка сохраняется а фон становиться стандартным, как это исправить ребят помогите...
Код Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Private Sub Надпись43_Click()
CurrentDb.QueryDefs("Просмотр пациент").SQL = ("SELECT Пациент.[Код пациента], Пациент.[ФИО пациента], Пациент.[Дата рождения], Пациент.Адрес, Пациент.Телефон, Пациент.Паспорт FROM Пациент ORDER BY Пациент.[ФИО пациента]")
DoCmd.Requery
Надпись57.BackColor = RGB(255, 255, 255)
Надпись43.BackColor = RGB(0, 255, 191)
Надпись44.BackColor = RGB(255, 255, 255)
Надпись46.BackColor = RGB(255, 255, 255)
Надпись45.BackColor = RGB(255, 255, 255)
Надпись47.BackColor = RGB(255, 255, 255)
End Sub
 
Private Sub Надпись43_DblClick(Cancel As Integer)
CurrentDb.QueryDefs("Просмотр пациент").SQL = ("SELECT Пациент.[Код пациента], Пациент.[ФИО пациента], Пациент.[Дата рождения], Пациент.Адрес, Пациент.Телефон, Пациент.Паспорт FROM Пациент ORDER BY Пациент.[ФИО пациента] DESC")
DoCmd.Requery
Надпись57.BackColor = RGB(255, 255, 255)
Надпись43.BackColor = RGB(0, 204, 204)
Надпись44.BackColor = RGB(255, 255, 255)
Надпись46.BackColor = RGB(255, 255, 255)
Надпись45.BackColor = RGB(255, 255, 255)
Надпись47.BackColor = RGB(255, 255, 255)
End Sub 
Ответ: no0t24, ответ Волшебника не смотрел, но избавляюсь от этого с.о.:на событии формы (скажем Form_Current) делаю исходную сортировку
Вопрос: Присвоить значение выпадающему списку из списка другой формы

Здравствуйте, решил упростить работу с формами, а именно передать значение из списка 1й формы в поле с выпадающим списком 2й формы для дальнейшей работы, но возникла проблема.
Присваивал значения так (событие при загрузке второй формы):

SQL
1
2
a = Forms!Форма1.Controls!СписокПервойФормы.COLUMN(0)
Me.ВыпадающийСписокВторойФормы = a
Значение в поле с вып. списком второй формы появляется, но с ним нельзя работать (будто его и нет, лишь визуально отображается), пока не раскрыть список и не выбрать элемент, т.е. никакого упрощения - пользователю нужно выбирать элемент так же, как если бы значение в списке было изначально пустое.
Как решить эту проблему? Может как-то возможно программно выбрать уже выбранное значение в вып. списке?
Ответ: mobile,
Спасибо большое, все работает! Пытался и обновлять список и как-то неудачно выбирать значение, а до кода, который вы привели, даже бы и не додумался.
Вопрос: Передача параметра из закрываемой формы

Помогите решить проблемку, никак не соображу. Есть форма, на ней есть кнопка по которой с помощью DoCmd.Open открывается другая форма для ввода поля. После ввода этого поля вторая форма закрывается и должна передать значение этого поля в форму из которой вызывалась эта вторая форма. Никак не соображу, как передать это значение?
Ответ: Ну да, логично..слишком закапываться стал, а решение было на поверхности. Спасибо! Получилось
Вопрос: Передача параметра из формы с таблицей в другую форму

Существует таблица1 и таблица2, которые построены на основании запроса(просто разные виды таблиц на форме).

Как сделать что б при двойном клике мыши на строку в таблице1 или таблице2 загружалась форма "Добавление работы", далее выбираем работу и при нажатии на кнопку "Ок", код вида работ записывался к пользователю, которого выбрали ранее в таблице в строку данного пользователя в поле "Код_работы" в форму с таблицей1 или таблицей2?

База для примера.
Ответ: Приведенный пример я специально переписал что б было поменьше кнопочек там нужно еще добавлять функционал еще дополнительно о котором я не говорил, но буду его делать.

Но самое сложно это передать параметр выбранной строки в форму.
Далее я думаю у меня не должно будет возникнуть сложности.
далее в форме уже создать новую запись или выбрать из существующей и потом определенную циферку записи выбранной или созданной записать в ранее выбранную запись в определенное поле.
Вопрос: Передача значения поля из одной формы в другую

Здравствуйте! Подскажите, пожалуйста, как передать значения полей из одной формы в другую? Т.е. у меня есть на первой форме Поле1 и Поле2, после нажатия на кнопку, значение этих полей передаётся на вторую форму в такие же поля.
Ответ:
Сообщение от mobile
Из хелпа
Ну да, будем теперь хэлп сюда копипастить.
Вопрос: Как передать параметр Cancel, из события Выгрузка в стандартный модуль?

Хочу перенести эту процедуру в стандартный модуль, поскольку к ней будут обращаться несколько форм. В общем столкнулся с тем, что параметр Cancel не работает в стандартном модуле.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Private Sub Form_Unload(Cancel As Integer) 'На событии Выгрузка, если флажок взведен, то показать сообщение с вариантами: Заполните поле... или удалить запись
 
''На редактирование новой записи
    If sDrt And sNewRec Then
        'цикл
        Dim i, arr
 
        'Массив имен обязательных полей записанных в нужном порядке
        arr = Array("КодКлиент", "КодОперация", "КодТипНедвижимости", "КодУлица", "№Дома", "КодИсточникИнформации", "№Договора", "ДатаДоговора", "КодСотрудник", "КодСтатус")
 
        For i = 0 To UBound(arr)                                 'Цикл по массиву имен
            Debug.Print i, arr(i), Me.Controls(arr(i)).Name      'Распечатка последовательности прохода
            'Нужно прописать по пути: Окно свойств-другие-доплнительные сведения - значение "Обязательное"
            If Me.Controls(arr(i)).Tag = "обязательное" And IsNull(Me.Controls(arr(i))) Then
                Select Case MsgBox("Заполните поле " & Me.Controls(arr(i)).Name, vbOKCancel + vbExclamation + vbDefaultButton1)
                Case vbOK
                    Cancel = True   'отмена закрытия, возврат в форму
                    Me.Controls(arr(i)).SetFocus    'Me.Controls(arr(i)).SetFocus равнозначно Me![КодКлиент].SetFocus
            Exit Sub 'выходим из процедуры, иначе будут перебираться все контролы(поля)
                Case vbCancel
                    CurrentDb.Execute "delete * from Договора where КодНедвижимость=" & sID 'Удаляем только в такой последовательности:сначала подчиненная таблица, потом главная
                    CurrentDb.Execute "delete * from Недвижимость where КодНедвижимость=" & sID
                End Select
            Exit Sub    'выходим из процедуры, иначе будут перебираться все контролы(поля)
            End If
        Next
    End If
End Sub
Добавлено через 8 минут
Нашел в макросах и преобразовал, вроде работает...)
Visual Basic
1
DoCmd.CancelEvent
Ответ: alvk, Понял, не совсем дурак, чё на весь мир та кричать та.