Для первых 3 таблиц, упомянутых в вашем комментарии, у каждой должен быть первичный ключ: Customers, customer_id; продукты, product_id; и сотрудники, employee_id.
Таблица кавычек будет иметь свой собственный первичный ключ quote_id и будет хранить customer_id и employee_id в качестве внешних ключей. (Я предполагаю, что вы хотите, чтобы employee_id записывал, какой представитель клиента / продавец создал цитату.) Вы также можете включить дополнительные атрибуты для каждой цитаты; например, цитата из даты и времени.
Продукты, предлагаемые для котировок, будут храниться в распределительной таблице QuoteProducts. Он будет иметь внешние ключи для quote_id и product_id, по одной строке для каждого продукта, предлагаемого в цитате. Здесь также можно хранить количество атрибутов и скидки. В дополнительном поле unit_price можно сохранить цену продукта, которая действовала на момент составления предложения ... что было бы полезно в случае изменения цен на продукт с течением времени. Я не знаю, должен ли налог быть включен в эту таблицу (см. Ниже).
Я также не знаю, как решить проблему доставки. Если все продукты, связанные с предложением, предназначены для доставки в одной поставке, стоимость доставки может быть атрибутом таблицы предложений. Я не знаю, как вы намереваетесь получить это значение. Похоже, это может быть определено методом доставки, расстоянием и весом. Если у вас есть продавец, который вычисляет это значение отдельно, а затем вводит значение, подумайте, как обработать случай, когда выбор продукта изменяется после того, как была введена плата за доставку.
Этот дизайн несколько упрощен, но может оказаться достаточным для описанной вами ситуации. Тем не менее, это может стать более сложным. Например, если вы решите вести историю изменений цен на продукты, вам лучше было бы создать условия для этого сейчас. Кроме того, я понятия не имею, как в вашей ситуации применяется налог - применяется ли он ко всем продуктам по единой ставке, зависит от местоположения клиента, зависит от типа клиента и / или зависит от продукта. Ваши бизнес-правила для налогов должны быть учтены при разработке схемы.
Однако, если этот дизайн работает для вас (проверьте его, введя фиктивные данные в таблицы без использования формы), вы можете создать форму на основе кавычек с подчиненной формой на основе QuoteProducts. С quote_id в качестве свойства master / child ссылки, подчиненная форма позволит вам просматривать все продукты, связанные с текущим quote_id основной формы. Вы можете использовать подчиненную форму для добавления, удаления и / или редактирования продуктов, связанных с этой цитатой.
Не так много я могу сказать об отчете. Существует много неопределенности в предыдущем описании. Однако, если ваш дизайн базы данных позволяет вам создать работоспособную форму / подчиненную форму, он также должен поддерживать запрос, который собирает те же данные. Используйте этот запрос в качестве источника записи для отчета. И используйте функции сортировки и группировки отчета для создания итоговой суммы цитаты.
Редактировать : При использовании подхода основной формы / подчиненной формы каждая новая строка в подчиненной форме должна «наследовать» значение quote_id текущей записи в основной форме. Вы гарантируете это, устанавливая свойства master / child ссылки на quote_id. Crystal Long объясняет это более подробно в главе 5 Основы доступа Crystal : PDF-файл . Прокрутите вниз до заголовка Создание главной формы и подчиненной формы на странице 24.
Edit2 : Ваша стратегия может включать хранение Products.ListPrice в QuoteDetails.ListPrice. Это было бы полезно для записи текущего ListPrice, предлагаемого для цитаты. Если это так, вы можете получить ListPrice из Products и сохранить его в QuoteDetails при выборе ProductID для строки в подчиненной форме. Это можно сделать с помощью кода VBA в событии после обновления элемента управления, который связан с полем ProductID. Поэтому, если этот элемент управления является комбинированным полем с именем cboProductID, а элемент управления подчиненной формы, связанный с полем QuoteDetails ListPrice, является текстовым полем с именем txtListPrice, используйте такой код для cboProductID после обновления:
Me.txtListPrice = DLookup("ListPrice", "Products", "ProductID = " _
& Me.cboProductID)
В этом предложении предполагается, что таблицы Products и QuoteDetails содержат поле ProductID, а его тип данных - числовой. И cboProductID имеет ProductID в качестве своего связанного поля и использует запрос в качестве RowSource, подобный этому:
SELECT ProductID, ProductName
FROM Products
ORDER BY ProductName;