MS-Access: что может привести к тому, что одна форма с запросом на соединение загрузится правильно, а другая - нет? - PullRequest
0 голосов
/ 11 марта 2010

Последние новости!

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


Form1

Форма 1 связана с таблицей 1. Таблица1 имеет поле идентификатора.

Form2

Форма 2 связана с таблицей 2, соединенной с таблицей 1 таблицы 2. Таблица1_ID = Таблица1.ID

Вот SQL (сгенерированный Access):

SELECT
  Table2.*,
  Table1.[FirstFieldINeed],
  Table1.[SecondFieldINeed],
  Table1.[ThirdFieldINeed]
FROM Table1 INNER JOIN Table2 ON Table1.ID = Table2.[Table1_ID];

Form2 открывается с этим кодом в Form1:

DoCmd.RunCommand acCmdSaveRecord
DoCmd.OpenForm "Form2", , , , acFormAdd, , Me.[ID]
DoCmd.Close acForm, "Form1", acSaveYes

А при загрузке запускается:

Me.[Table1_ID] = Me.OpenArgs

Когда загружена Form2, поля, связанные со столбцами из Table1, отображаются правильно.

Форма Form3

Форма 3 связана с таблицей 3, соединенной с таблицей 2 таблицы 3. Таблица 2. ID = Таблица 2. ID

Вот SQL (сгенерированный Access):

SELECT
  Table3.*,
  Table2.[FirstFieldINeed],
  Table2.[SecondFieldINeed]
FROM Table2 INNER JOIN Table3 ON Table2.ID = Table3.[Table2_ID];

Форма 3 открывается с этим кодом в форме 2:

DoCmd.RunCommand acCmdSaveRecord
DoCmd.OpenForm "Form3", , , , acFormAdd, , Me.[ID]
DoCmd.Close acForm, "Form2", acSaveYes

А при загрузке работает:

Me.[Table2_ID] = Me.OpenArgs

Когда загружена форма 3, поля, связанные со столбцами из таблицы 2 , не отображаются правильно.

ПОЧЕМУ?


ОБНОВЛЕНИЕ

Я попытался создать запрос на объединение в отдельный запрос и использовать его в качестве источника записей, но это не имело никакого значения.

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


Очередной раунд обновлений

Позвольте мне привести аналогичную ситуацию, поэтому то, что я пытаюсь сделать, понятно.

Table1 теперь Дома. Table2 теперь Драйверы. Table3 теперь Cars.

Притворись, что я пишу заявление о страховании. Соотношение этих таблиц будет точно соответствовать тому, что я пытаюсь сделать.

В каждом доме может быть один или несколько водителей, а у каждого водителя ровно одна машина. Сейчас я просто пытаюсь заставить его работать с одним домом, одним водителем и одной машиной. Пользователь должен сначала увидеть форму HouseInformation, которая попросит его заполнить информацию о своем доме. Затем они увидят DriverInformation, который попросит их заполнить информацию о себе. Затем они увидят CarInformation, который попросит их заполнить информацию об их автомобиле. После того, как они будут сделаны, в каждой таблице будет одна запись. Запись в Drivers будет содержать HouseId, соответствующий соответствующему дому, а запись в Cars будет содержать DriverId, соответствующий соответствующему водителю. Меня не особо волнует, как связаны формы, просто они есть и работают надежно.

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


Дополнительные обновления

Субформы не приемлемы для клиента, который специально запросил отдельные формы.

Я нахожу это чрезвычайно запутанным, но после загрузки Form3, если я его закрываю, перехожу в представление конструктора, открываю запрос для Form3 и переключаюсь в представление таблицы данных, там отображаются правильные данные, включая поля, которые я хочу получить из Form2. Это просто не будет отображаться в форме. Я запросил. Это не имеет значения. Это не будет отображаться.

Ответы [ 4 ]

1 голос
/ 20 марта 2010

Я создал базу данных Access 2007, пытаясь максимально имитировать таблицы / формы / код, перечисленные выше (автомобили, драйверы и т. Д.). Все работает как положено , когда я удаляю Me.[ID] как OpenArgs из команды DoCmd.OpenForm. Еще одна вещь, которую нужно проверить, если это не сработает, это отношения между таблицей 2 и таблицей 3, чтобы увидеть, все ли они в такте.

Вы правы, это действительно распространенный сценарий, и обычно он должен работать, как вы описали выше.

0 голосов
/ 25 марта 2010

Мне удалось воссоздать вашу структуру и заставить ее работать должным образом (то есть значения таблицы 2 отображаются в форме 3 с данными таблицы 3) в Access 2007.

Сначала я создал три таблицы (для этого я буду использовать псевдо-SQL-синтаксис)

Схема

Create Table Table1 ( Table1_ID AutoNumber, Col1 Text )
Create Table Table2 ( Table2_ID AutoNumber, Table1_ID Number, Col1 Text )
Create Table Table3 ( Table3_ID AutoNumber, Table2_ID Number, Col1 Text )

I created a relation from Table1 to Table2 with Enforce RI on.
I created a relation from Table2 to Table3 with Enforce RI on.

Insert Into Table1(Col1) Values("Val1")
Insert Into Table1(Col1) Values("Val2")
Insert Into Table1(Col1) Values("Val3")

Insert Into Table2(Table1_ID, Col1) Values(1, "T2Val1")
Insert Into Table2(Table1_ID, Col1) Values(2, "T2Val2")
Insert Into Table2(Table1_ID, Col1) Values(3, "T2Val3")

Insert Into Table3(Table1_ID, Col1) Values(1, "T3Val1")
Insert Into Table3(Table1_ID, Col1) Values(2, "T3Val2")
Insert Into Table3(Table1_ID, Col1) Values(3, "T3Val3")

Форма 1 (используется Волшебник)

Form.Control Source = Table1
TextBox control named Table1_ID with a Control Source=Table1_ID
TextBox control named Col1 with a Control Source=Col1
Command Button with Click event set to:
    DoCmd.RunCommand acCmdSaveRecord
    DoCmd.OpenForm "Form2", , , , acFormAdd, , Me.[Table1_ID]
    DoCmd.Close acForm, "Form1", acSaveYes

Форма 2

Form.Control Source = SELECT Table2.*, Table1.Col1 FROM Table1 INNER JOIN Table2 ON Table1.Table1_ID=Table2.Table1_ID; 
Form_Load event set to
    Me.[Table1_ID] = Me.OpenArgs
TextBox control named Table2_ID with a Control Source=Table2_ID
TextBox control named Table2.Col1 with a Control Source=Table2.Col1
TextBox control named Col1 with a Control Source=Table1.Col1
Command Button with Click event set to:
    DoCmd.RunCommand acCmdSaveRecord
    DoCmd.OpenForm "Form3", , , , acFormAdd, , Me.[Table2_ID]
    DoCmd.Close acForm, "Form2", acSaveYes

Форма Form3

Form.Control Source = SELECT Table3.*, Table2.Col1 FROM Table2 INNER JOIN Table3 ON Table2.Table2_ID=Table3.Table2_ID; 
Form_Load event set to
    Me.[Table2_ID] = Me.OpenArgs
TextBox control named Table3_ID with a Control Source=Table3_ID
TextBox control named Table2_ID with a Control Source=Table2_ID
TextBox control named Col1 with a Control Source=Table2.Col1

Шаги для воспроизведения (обратите внимание, что конкретные идентификаторы могут отличаться):

1. Open Form1 
    a. Table1_ID: 1
    b. Col1: Val
2. Click the Button.
3. Form2 Opens in add mode.
    a. Table2_ID shows next ID (probably 4)
    b. Table2.Col1: <blank>
    c. Table1.Col1: Val1
4. Enter "FOO" in the TextBox for Table2.Col1 and Click the button
5. Form3 Opens in add mode
    a. Table3_ID: next id (probably 4)
    b. Table2_ID: the id shown in Step 3a.
    c. Table2.Col1: FOO

Ключом к выполнению этой работы является шаг 4: ввод значения для Col1 . Если в Form2 вы просто нажимаете кнопку, чтобы перейти к Form3, вы создаете пустую запись Table2 и связываетесь с новой записью Table3, поэтому в Form3 ничего не будет отображаться.

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

Теперь, все сказанное, я бы не подошел к этому решению таким образом. Во-первых, я хотел бы убедиться, что у меня есть префикс каждого имени элемента управления (например, lbl, txt и т. Д.). Я обнаружил, что иногда Access может запутаться между ссылками на элемент управления с тем же именем, что и у Field. Во-вторых, привязка редактируемой формы к запросу с объединением - это рецепт боли IMO. Вместо этого я бы связал непосредственно с рассматриваемой таблицей и использовал подчиненную форму или просто запросил в коде VBA из события Load необходимые данные из родительской таблицы и связал бы их вручную.

0 голосов
/ 22 марта 2010

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

0 голосов
/ 20 марта 2010

Обычно это делается с подчиненными формами. Есть два подхода к этому:

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

  2. каскадные подчиненные формы.

Домохозяйства будут вашей родительской формой.

Ваш стол Cars будет иметь внешний ключ HouseholdID.

Ваша таблица драйверов будет иметь внешний ключ CarID.

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

У вас также есть подчиненная форма драйверов, которая для первого решения, которое вы вставляете в подчиненную форму Cars, связана с CarID. Это вынуждает форму машины быть единой формой или, что более полезно, формой таблицы данных. Вы можете сделать драйверы формой непрерывной или таблицы данных, потому что она находится внизу вложенных форм.

Результатом является подчиненная форма, которая отображается в виде таблицы данных и имеет вложенную таблицу. Когда вы нажимаете кнопку со звездочкой в ​​техническом описании автомобиля, вы получаете новую запись и вводите данные автомобиля. Идентификатор домохозяйства вводится автоматически (именно так работают подчиненные формы). Аналогично, для водителей вы нажимаете звездочку в подчиненной форме драйверов и вводите драйвер.

Если вы не хотите ограничиваться таблицами данных, вы можете поместить обе подчиненные формы в форму домохозяйств верхнего уровня и связать форму драйверов на CarID из подчиненной формы следующим образом:

LinkChildField: CarID LinkParentField: Cars.Form! CarID

Это вызывает некоторые проблемы с пользовательским интерфейсом, поскольку вы не можете ввести драйвер, пока автомобиль не введен, и у вас могут возникнуть проблемы. Это не относится к решению 1, которое, поскольку оно использует таблицы данных, не вызывает проблем с пользовательским интерфейсом.

Одна из проблем, связанных с этим решением, заключается в том, что если вы хотите подключить одного водителя к нескольким автомобилям в домашнем хозяйстве, вам необходимо ввести водителя дважды. Решением этой проблемы является создание таблицы соединений для подключения нескольких автомобилей к нескольким водителям. Эта таблица будет содержать CarID и DriverID, а ваша низкоуровневая подчиненная форма в описанной выше настройке будет tblCarDriver в качестве источника записей и поле со списком в качестве единственного элемента управления, извлекающего данные из таблицы Drivers. Поле со списком будет привязано к DriverID таблицы соединений.

Теперь это позволяет вам смоделировать двух водителей в одном домохозяйстве за рулем двух автомобилей без необходимости вводить каждого водителя дважды, но в этой настройке нет места для ввода нового водителя. Итак, обычный метод - установить событие NotInList для поля со списком и при вводе «Fenton, David W.» в поле со списком, и его там нет, он спрашивает вас, хотите ли вы ввести его как новый драйвер, а затем код в событии NotInList позаботится об этом за вас (либо принимая то, что вы вводите, и вставляя запись, либо открывая всплывающая форма, предварительно заполненная введенными вами данными, которая позволяет вводить другую информацию, например номер телефона, адрес электронной почты и т. д.).

Вот скриншот моего уродливого макета первого решения с объединением множества людей между автомобилями и водителями:

alt text
(источник: dfenton.com )

...