Как связать формы в Access? (передать значения между ними) - PullRequest
2 голосов
/ 03 июня 2010

Я использую Access 2007 и у меня есть такая модель данных ...

Пассажир - Бронирование - Направления

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

Моя проблема ...

Я могу создать форму, позволяющую вводить данные Пассажира, но затем я хочу добавить СЛЕДУЮЩУЮ кнопку, чтобы перейти в форму для ввода информации о бронировании (то есть, просто выпадающий список пунктов назначения). Я добавил кнопку «СЛЕДУЮЩАЯ», и у нее есть события

RunCommand SaveRecord
OpenForm   Destination_form

НО, я не могу понять, как передать в новую форму первичный ключ только что введенного пассажира (PassengerID).

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

Может кто-нибудь помочь мне, пожалуйста?

Спасибо Джефф Портер

Ответы [ 5 ]

7 голосов
/ 03 июня 2010

На самом деле лучшее предложение, которое я могу дать, это не передавать параметры. Простое в открытии вашей формы событие или, что еще лучше, использование более позднего события загрузки - просто подобрать ссылку в вашем коде на ПРЕДЫДУЩУЮ форму вызова. Прелесть этого подхода в том, что если вы переходите от одного параметра к 10 параметрам сверхурочно, вам не нужно изменять код разбора параметров и даже не нужно изменять вызывающий код. На самом деле нет кода для изменения ВСЕГО, если вы решите проверить предыдущие значения из формы вызова.

Итак, имейте в виду, что использование открытых аргументов - это только один из способов. Вы не можете использовать его для возврата значений в форму вызова. Кроме того, все параметры open args должны быть строками. Таким образом, вы теряете любую возможность типирования датировки, например, целых чисел или даже форматирования даты и времени, что может быть довольно проблематичным для анализа. И, как вы можете видеть на примере, приведенном здесь, код для разбора строк в любом случае может немного запутаться.

Простое решение состоит в том, что в каждой форме, в которой вы хотите получить значения из ПРЕДЫДУЩЕГО, просто объявите переменную уровня модуля следующим образом

Dim frmPrevous         as form.

Затем в ваших формах при загрузке события просто выберите название предыдущей формы следующим образом:

Set frmPrevious = screen.ActiveForm

Вот и все. Мы сделали!

Мы написали здесь только одну строку кода. (Хорошо, если вы включите декларацию). На этом этапе слова ЛЮБОЕ место в текущем коде вашей формы вы можете ссылаться на свойства событий и любое поле или значение в предыдущей форме, выполнив следующую команду

Msgbox "PK id of previous form = " & frmPrevious.ID

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

frmPrevious.Requery

Или принудительно сохранить запись:

frmPrevious.Dirty = false

Итак, вышеизложенное становится почти таким же естественным и удобным, как использование «ME» в вашем текущем коде. Я нахожу это настолько простым и легким, что, я думаю, это должно было быть частью доступа.

И как уже упоминалось, использование бесконечно, я могу проверить ЛЮБОЙ столбец или значение из формы вызова. Вы даже можете объявить переменные и функции как общедоступные, а затем их можно использовать.

И обратите внимание, что это работает ОБА ПУТИ. Я могу набивать и изменять значения в форме вызова. Поэтому я могу обновить или изменить значение любого значения / столбца / элемента управления из формы вызова.

И разбор абсолютно не требуется. Кроме того, вышеприведенный шаг кода работает, даже если одна и та же существующая форма вызывается разными формами. Во всех случаях формы, вызывающие ID, могут быть получены без изменения вашего кода.

И даже в случае, когда у меня есть много разных форм, запускающих и вызывающих эту конкретную форму, вы все равно можете извлечь столбец ID. И в случае, если столбцы могут отличаться от разных форм, вы можете просто объявить открытые переменные или публичные функции в вызывающей форме одного и того же имени. Итак, если я хотел вызвать форму, которая нуждается в DateCreate, но у каждой формы НЕ было согласованного имени столбца DateCreate (возможно, invoiceDateCreate и инвентаризации Date Create), то вы просто объявляете открытую функцию в вызывающих формах с постоянным именем , Затем мы можем пойти:

Msgbox "Date created of calling form record = " & frmPrevious.DateCreated

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

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

Вы также можете вернуть значения в форму вызова, просто установив значение любого элемента управления, который вы хотите (frmPrevous.SomeContorlName).

И, как уже упоминалось, вы не ограничены просто передачей значений, но имеете полное использование кода, таких свойств, как dirty, и любых других вещей, которые существуют в вызывающей форме.

В качестве стандартной практики кодирования я принял вышеизложенное почти для каждой формы. Я просто заявляю и настраиваю форму предыдущей ссылки. Это приводит к удобной ссылке на предыдущую форму, так же полезной, как ссылка «ME» при написании кода.

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

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

frmPrevious.MyDelete

Так что я могу сохранить данные в предыдущей форме. Я могу запросить предыдущую форму, я могу запустить код в предыдущей форме, я могу вернуть значения в предыдущую форму, я могу исследовать значения и все столбцы по цене только ОДНОЙ жалкой строки кода, которая устанавливает ссылку на вызов форма.

1 голос
/ 05 июня 2010

Я делаю это, определяя свойства в форме с помощью свойства Let и Property Get и передавая значения этим свойствам после открытия формы, например:

в форме назначения:

Dim strCallingForm As String
Dim lngKey As Long

Public Property Get callingform() As String
    callingform = strCallingForm
End Property

Public Property Let callingform(NewValue As String)
    strCallingForm = NewValue
End Property

Public Property Let PrimaryKey(NewValue As Long)
    lngKey = NewValue
End Property

в форме вызова:

Sub btnGo_Click()
    Const cform As String = "frmDestinationForm"
    DoCmd.OpenForm cform
    Forms(cform).callingform = Me.Name
    Forms(cform).PrimaryKey = Me.PrimaryKey
    Me.Visible = False
End Sub

(окончание)

0 голосов
/ 03 июня 2010

Вы можете использовать OpenArgs.
Но я бы также посоветовал вам рассмотреть возможность использования элемента управления с вкладками.Это позволяет вам иметь разные наборы элементов управления в одной «области экрана», используя один единственный набор записей или используя подформы для отображения дочерних наборов записей.
В этом случае вы можете использовать кнопку «Далее», чтобы просто переключатьсяна следующую страницу элемента управления вкладкой.

0 голосов
/ 03 июня 2010

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

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

2007 http://office.microsoft.com/en-us/templates/TC012289971033.aspx?CategoryID=CT102115771033

2000 http://www.microsoft.com/downloads/details.aspx?familyid=c6661372-8dbe-422b-8676-c632d66c529c&displaylang=en

0 голосов
/ 03 июня 2010

Я бы использовал метод openargs формы. Таким образом, вы можете передать один фрагмент данных в новую форму из любой другой формы. Вы также можете расширить это, отправив разделенную строку аргументов, а затем разделив их. Например, у меня есть форма для редактирования действия агента, в которой передается дата, имя агента, идентификатор агента и команда в открытых аргументах

DoCmd.OpenForm "frmEdit_agent_activity", , , , , acDialog, Item & "|" & Me.txtDate & "|" & Item.ListSubItems(1) & "|" & Item.ListSubItems(2)

Форма затем использует это для предварительного заполнения элементов управления

Private Sub Form_Load()
If IsMissing(Me.OpenArgs) = True Or IsNull(Me.OpenArgs) = True Then
    'no args, exit the form
    DoCmd.Close acForm, "frmEdit_agent_activity", acSaveNo
Else
    'this form has 4 open args
    '1 Staff ID
    '2 Date
    '3 Team_ID
    '4 Staff Name
    Me.txtStaff_ID = GetDelimitedField(1, Me.OpenArgs, "|")
    Me.txtDate = GetDelimitedField(2, Me.OpenArgs, "|")
    Me.txtTeam_ID = GetDelimitedField(3, Me.OpenArgs, "|")
    Me.txtStaff_name = GetDelimitedField(4, Me.OpenArgs, "|")
End If

End Sub

Ооо, а вот и функция GetDelimitedField

Function GetDelimitedField(FieldNum As Integer, DelimitedString As String, Delimiter As String) As String
Dim NewPos As Integer
Dim FieldCounter As Integer
Dim FieldData As String
Dim RightLength As Integer
Dim NextDelimiter As Integer
If (DelimitedString = "") Or (Delimiter = "") Or (FieldNum = 0) Then
    GetDelimitedField = ""
    Exit Function
End If
NewPos = 1
FieldCounter = 1
While (FieldCounter < FieldNum) And (NewPos <> 0)
    NewPos = InStr(NewPos, DelimitedString, Delimiter, vbTextCompare)
    If NewPos <> 0 Then
        FieldCounter = FieldCounter + 1
        NewPos = NewPos + 1
    End If
Wend
RightLength = Len(DelimitedString) - NewPos + 1
FieldData = Right$(DelimitedString, RightLength)
NextDelimiter = InStr(1, FieldData, Delimiter, vbTextCompare)
If NextDelimiter <> 0 Then
FieldData = Left$(FieldData, NextDelimiter - 1)
End If
GetDelimitedField = FieldData
End Function
...