Подчиненный справочник 1С
В прикладных задачах иногда возникают ситуации, когда элемент какого-нибудь справочника должен быть жестко подчинен элементу другого справочника. Например, у контрагентов могут существовать договоры, которые заключены с организацией, ведущей учёт. Тогда, экземпляр справочника Договоры контрагента должен быть подчинен справочнику Контрагенты, поскольку, мы не можем создать договор сам по себе, договор должен быть привязан к конкретному контрагенту. Для реализации подобных задач необходим подчиненный справочник 1С. В выше приведенном случае, справочник Договоры контрагента станет подчинен справочнику Контрагенты. А справочник Контрагенты будет являться владельцем справочника Договоры контрагента.
Конструируем подчиненный справочник 1С
Для того, чтобы из справочника 1С сделать подчиненный справочник, достаточно в редакторе справочника на закладке Владельцы указать владельца этого справочника.

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

После таких манипуляций, нельзя создать этот справочник (в рассматриваемом примере – ДоговорыКонтрагента) без указания владельца (Контрагента).
Если мы попробуем создать, элемент справочника ДоговорыКонтрагента, то поле, в котором следует указать контрагента-владельца будет обязательным для заполнения.

Заметьте, это поле называется Владелец и является стандартным реквизитом справочника.

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

После выполнении этой команды, откроется форма списка с элементами подчиненного справочника, у которых владелец ссылка на открытый элемент справочника Контрагенты.

Программное создание элемента подчиненного справочника
Разберем программное создание элемента подчиненного справочника. Оно выполняется при помощи метода менеджера справочник СоздатьЭлемент. Только, в случае подчиненных справочников обязательно нужно указать владельца!
Например, создадим обработку, на управляемой форме которой разместим реквизиты Владелец (тип ссылка на справочник Контрагент) и Название договора, а также команду Создать подчиненный справочник.

При выполнении этой команды, будем создавать экземпляр справочника Договоры контрагента, который подчинен указанному владельцу.
&НаСервере Процедура СоздатьПодчиненныйСправочникНаСервере() НовыйДоговор = Справочники.ДоговорыКонтрагента.СоздатьЭлемент(); НовыйДоговор.Наименование = НазваниеДоговора; НовыйДоговор.Владелец = Владелец; НовыйДоговор.Записать(); КонецПроцедуры &НаКлиенте Процедура СоздатьПодчиненныйСправочник(Команда) Если Не ПроверитьЗаполнение() Тогда Возврат; КонецЕсли; СоздатьПодчиненныйСправочникНаСервере(); КонецПроцедуры
В клиентской процедуре используется проверка заполнения. Подробнее о проверке читайте в этой статье:
Выбор элементов подчиненного справочника на управляемой форме
Часто возникают задачи, когда на управляемой форме размещены поля ввода и для справочника владельца, и для подчиненного справочника. И в этом случае нужно реализовать, чтобы в поле ввода подчиненного справочника отображались только те элементы, владелец которых указан в поле ввода справочника владельца.
Например, у документа Продажа товаров существуют реквизиты Контрагент и Договор контрагента соответствующих типов.

Для того, чтобы в реквизите Договор контрагента можно было выбрать только договоры указанного контрагента, следует в палитре свойств реквизита объекта у свойства Связи параметров выбора сделать настройку, в которой указать, что реквизит Контрагент используется при выборе значений в качестве владельца.


После таких настроек, в поле ввода Договоры контрагента можно выбрать только договоры, указанного контрагента.

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

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

Поиск среди подчиненных справочников
Для того, чтобы найти какой-то элемент среди подчиненных справочников, при помощи методов менеджера справочника НайтиПоНаименованию, НайтиПоКоду и НайтиПоРеквизиту следует использовать параметр Владелец этих методов.
Например, в случае поиска по наименованию, код будет следующим.
Договор = Справочники. ДоговорыКонтрагента.НайтиПоНаименованию(НазваниеДоговора,Истина,,Владелец);
Где НазваниеДоговора – это наименование элемента справочника, который ищется.
Владелец – это ссылка на справочник владелец.
Подчиненный справочник 1С или табличная часть?
Часто возникает вопрос: чем отличается подчиненный справочника от табличной части. Основной ответ, тем что у элемента подчиненного справочника имеется ссылка на этот элемент, а у строки табличной части такой ссылки нет.
Подробно, о том, что выбрать при разработке подчиненный справочник или табличную часть читайте по этой ссылке на сайте its.1c.ru:
Читайте также по теме:
Более подробно и основательно начальные вопросы программирования в 1С есть вы можете изучить в
Книга «Программировать в 1С за 11 шагов»
Изучайте программирование в 1С в месте с моей книгой «Программировать в 1С за 11 шагов»

Книга написана понятным и простым языком — для новичка.
- Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
- Научитесь понимать архитектуру 1С;
- Станете писать код на языке 1С;
- Освоите основные приемы программирования;
- Закрепите полученные знания при помощи задачника
О том как разрабатывать под управляемым приложением 1С, читайте в книге Книга «Основы разработки в 1С: Такси»
Отличное пособие по разработке в управляемом приложении 1С, как для начинающих разработчиков, так и для опытных программистов.

- Очень доступный и понятный язык изложения
- Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
- Поймете идеологию управляемого приложения 1С
- Узнаете, как разрабатывать управляемое приложение;
- Научитесь разрабатывать управляемые формы 1С;
- Сможете работать с основными и нужными элементами управляемых форм
- Программирование под управляемым приложением станет понятным
Промо-код на скидку в 15% — 48PVXHeYu
Эти книги, плюс книга по программированию оперативного учета имеются в едином комплекте: комплект книг по разработке в 1С.
Только для читателей моего блога,
промо-код на скидку в 300 рублей на весь комплект: blog
Если Вам понравился этот урок, был полезен или помог решить какую-нибудь проблему, то Вы можете поддержать мой проект, перечислив любую сумму.
можно оплатить вручную:
Вступайте в мои группы:
Предложение let (справочник по C#)
В выражении запроса иногда требуется сохранить результат вложенного выражения, который будет использоваться в последующих предложениях. Это можно сделать с помощью ключевого слова let , которое создает новую переменную диапазона и инициализирует ее, используя результат предоставленного выражения. После инициализации с использованием этого значения такую переменную диапазона нельзя использовать для хранения других значений. Тем не менее если переменная диапазона хранит запрашиваемый тип, к ней можно выполнять запросы.
Пример
В следующем примере показываются два способа использования let :
- Создание перечисляемого типа, к которому можно выполнять запросы.
- Реализация запроса с однократным вызовом ToLower для переменной диапазона word . Если ключевое слово let не используется, потребуется выполнять вызов ToLower в каждом предикате предложения where .
class LetSample1 < static void Main() < string[] strings = < "A penny saved is a penny earned.", "The early bird catches the worm.", "The pen is mightier than the sword." >; // Split the sentence into an array of words // and select those whose first letter is a vowel. var earlyBirdQuery = from sentence in strings let words = sentence.Split(' ') from word in words let w = word.ToLower() where w[0] == 'a' || w[0] == 'e' || w[0] == 'i' || w[0] == 'o' || w[0] == 'u' select word; // Execute the query. foreach (var v in earlyBirdQuery) < Console.WriteLine("\"\" starts with a vowel", v); > // Keep the console window open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); > > /* Output: "A" starts with a vowel "is" starts with a vowel "a" starts with a vowel "earned." starts with a vowel "early" starts with a vowel "is" starts with a vowel */
См. также
- Справочник по C#
- Ключевые слова запроса (LINQ)
- LINQ в C#
- LINQ
- Обработка исключений в выражениях запросов
Технология создания форм для работы со справочниками
Для начинающих, да и не только, программистов зачастую большой проблемой является создание однотипных форм для работы со справочниками и тому подобных задач. По крайней мере большое количество вопросов как на форумах так и лично, об этом свидетельствует. Поэтому и по просьбе одного из своих друзей я решил посвятить отдельную статью вопросу организации работыс формами — и в частности организации работы с однотипными формами. Ведь в крупных проектах не редкость огромное количество различных справочников — таких как справочники должностей, справочники подразделений, справочники типов выплат и несть им числа. Мало того, в процессе эксплуатации программы не редкость дополнительный рост числа справочников — что само по себе доставляет. Как же с этим бороться? Ответ на это я попытаюсь дать в своей статье. Хочу обратить внимание, что приведенные рекомендации основываются на личном практическом опыте разработки крупных программных систем. В статье будут рассмотрены две основные темы
- Использование в работе шаблон проектирования Модель-Представление-Контроллер (MVС)
- Динамическое создание форм, как это делаю я.
Эти две темы практически не отделимы друг от друга — по одной простой причине — если вы не пользуетесь MVС, рано или поздно, в сравнительно большом проекте, вы начнете писать жуткий «макаронный» код, в котором будете путаться сами. Что бы этого избежать — используйте хорошие шаблоны программирования.
Все примеры, которые приведены в данной статье опираются на средства разработки компании Borland — Borland Builder C++, но по сути могу применяться в любой системе вне зависимости от языка программирования. BCB используется здесь только потому, что на нем пишет человек, который попросил написать данную статью.
И так MVС. Что это такое, с чем ее едят и почему именно вам надо этот шаблон использовать? Все очень просто. основной принцип использования MVС заключается в разделении кода — если вы разделяете код, который получает данные из базы, от кода коорый эти данные обрабатывает и отдельно формируете код, который результат этой обработки показывает — поздравляю — вы используете MVС. Большинство удачных программных инструментов спроектировано таким образом, что следовать этому шаблону в них достаточно просто, легко и интуитивно понятно. Но как раз таки BCB и Delphi к таким системам не относятся (за что, я думаю, их создатели будут гореть в Аду — в специально для них созданном 10 круге), потому что в них чрезвычайно просто и легко писать «макаронный» быдлокод — когда все получение данных, их обработка и вывод запихивается в один единственный класс единственной формы, на которую горе программист накидал под сотню контролов — и весь этот, с позволения сказать, код размером в несколько тысяч строк компилируется в исполнимый файл и гордо называется «продуктом».
В принципе ничего конечно страшного в этом нет — если конечно не вам это все в последствии обслуживать и поддерживать. Потому что, в процессе обслуживания и поддержки работающей программы так или иначе приходится ее расширять, дорабатывать и… и вот тут то наступает армагедец. Потому что, через несколько месяцев уже плохо помниться зачем была написана та функция — которая вызывается по 20 раз в разных местах, и почему в некоторых местах в место этой функции вызывается совершенно другой код…ну и так далее. Те, кому приходилось поддерживать «продукты» жизнедеятельности таких вот «программистов» меня поймут.
Как реализовать все это на практике? Спроектируем небольшой модуль системы — предположим наш модуль будет реализовать следующую функциональность:
- Вывод и отображение записей различных справочников.
- Добавление, редактирование и удаление выбранных записей.
- Предоставление единого интерфейса для получения записей справочников (списки, деревья и пр.) в любой точке приложения.
Для начала вполне достаточно. Если использовать стандартный подход — то обычно создается форма, туда запихиваются нужные контролы и компоненты — потом создаются еще форма(а зачастую и не одна) для редактирования и добавления. Выборка данных из справочников выполняется в каждой точке приложения независимо.
Как это сделать с точки зрения MVС? Необходимо спроектировать четыре класса — класс-контроллер, класс доступа к данным, класс-форма основная и класс-форма добавления редактирования. Так как справочник по-английски Reference то соответственно классы лично я именую следующим образом:
- TRefernceController — класс контроллера, наследует от общего класса контроллера (если нужно);
- TmfMain — класс основной формы, наследует от TForm (BCB);
- TfmAddEdit — класс вспомогательной формы, наследует от TForm (BCB);
- TdmMain — модуль данных, наследует от TDataModule (BCB).
Естественно, наследование классов зависит от вашего конкретного приложения — я взял простейший вариант, что бы не слишком углубляться и не путаться. Название модулей — тоже зависит от того, какая система наименований принята у вас. Например, TmfMain — у меня имеет название любая основная форма модуля, но впрочем, это детали и я оставляю это на ваше рассмотрение.
Объевление класса контроллера может выглядеть примерно таким образом:
#ifndef loginH
#define loginH
#include
#include
#include
#include
#include
#include
#include
#include «main.h» //подключаем заголовочные файлы форм
#include «addedit.h»
class TReferenceController : public TGlobalController //если нужно, наследуем от своего общего класса
{
TfmMain * fmMain ;
TfmMain * dmMain ;
. //другие закрытые объявления
public :
__fastcall TRefernceController ( TConnection * db ) ;
void __fastcall getList ( TStrings * list, const int index ) ;
. //другие открытые методы
} ;
#endif
Как видим ничего особо сложного тут нет. Конкретная реализация контроллера зависит от задач приложения, но суть от этого не меняется — задача класса — обеспечивать всю работу с объектами, скрывая от пользователя-приложения все детали и тонкости. Основной момент — в конструктор класса я передаю указатель на существующее в приложении подключение — что бы было чем инициализировать модуль подключения к БД.
Класс модуля данных, в свою очередь, обеспечивает подключение к БД, получение необходимых данных, операции создания, редактирования и удаления данных в таблицах.
Его объявление может выглядеть примерно таким образом:
//—————————————————————————
class TdmMain : public TDataModule
{
__published : // IDE-managed Components
TADOConnection * adoConnect ;
TDataSource * dsListOrder ;
TADOQuery * adoListOrder ;
private : // User declarations
int UserId ;
//другие закрытые методы и свойства
public : // User declarations
__fastcall TdmMain ( TComponent * Owner, const bool visibleForm = true ) ;
__fastcall TdmMain :: TdmMain ( TComponent * Owner, TConnection * db ) ;
void __fastcall getListReference ( TStrings * list ) ;
//другие открытые методы
В описании форм нет ничего особенного, поэтому код приводить считаю тут излишним.
Общий алгоритм выглядит следующим образом:
- Приложение инициализирует модуль;
- Создает объект класса TReferenceController, путем вызова его конструктора и передав ему указатель на открытое соединение с БД;
- В качестве параметров конструктора создается объект модуля данных;
- Если установлен флаг создания формы — создаем форму.
Пример кода конструктора контроллера:
__fastcall TReferenceController :: TReferenceController ( TConnection * db, const bool visibleform ) : dmMain ( NULL ,db )
{
//если нужно — создаем форму, заполняем и показываем ее модально
if ( visibleForm )
{
fmMain = new TfmMain ( NULL ) ;
dmMain — > getListTab ( fmMain — > PageContorl, 0 ) ; //загружаем табы справочников и устанавливаем индекс
fmMain — > ShowModal ( ) ;
}
}
Думаю основная идея вполне понятна. Естественно, использование MVC немного усложняет жизнь на первом этапе — но зато значительно упрощает ее в дальнейшем.
Если же, идея с использованием контроллера все же вам кажется чересчур сложной — вы можете использовать упрощенный вариант — две формы и модуль данных. В таком случае получение, обработка и запись данных реализуется в модуле данных (dmMain) и соответственно там располагаются все компоненты для работы с БД. Формы в свою очередь реализуют отображение и обработку ввода данных.
И здесь основная проблема у начинающих возникает с тем, как создать динамически форму и передать ей нужные данные. Делается это следующим образом. Предположим что у нас в базе содержатся таблицы-справочники следующего вида:
CREATE TABLE [ dbo ] . [ Spr_Podr ] (
[ Kod ] [ int ] IDENTITY ( 1 , 1 ) NOT NULL , автоинкрементный
[ KodMR ] [ int ] NULL , код места работы
[ MR ] [ nvarchar ] ( 150 ) COLLATE Cyrillic_General_CI_AS NULL , название места работы
[ prMR ] [ nvarchar ] ( 250 ) COLLATE Cyrillic_General_CI_AS NULL , название места работы для формирования приказа
[ arh ] [ int ] NOT NULL признак записи в архиве 0 или 1
) ON [ PRIMARY ]
CREATE TABLE [ dbo ] . [ Spr_Slugb ] (
[ Kod ] [ int ] IDENTITY ( 1 , 1 ) NOT NULL , автоинкрементный
[ KodPodr ] [ int ] NULL , код службы ( отдела )
[ Podr ] [ nvarchar ] ( 250 ) COLLATE Cyrillic_General_CI_AS NULL , название службы ( отдела )
[ arh ] [ int ] NOT NULL признак записи в архиве 0 или 1
) ON [ PRIMARY ]
CREATE TABLE [ dbo ] . [ Spr_PodPodr ] (
[ Kod ] [ int ] IDENTITY ( 1 , 1 ) NOT NULL , автоинкрементный
[ KodPPodr ] [ int ] NULL , код подотдела
[ PodPodr ] [ nvarchar ] ( 255 ) COLLATE Cyrillic_General_CI_AS NULL , название подотдела
[ arh ] [ int ] NOT NULL признак записи в архиве 0 или 1
) ON [ PRIMARY ]
CREATE TABLE [ dbo ] . [ SprDolg ] (
[ id ] [ int ] IDENTITY ( 1 , 1 ) NOT NULL , автоинкрементный
[ Kod ] [ int ] NULL , код должности
[ Dolg ] [ nvarchar ] ( 150 ) COLLATE Cyrillic_General_CI_AS NULL , название должности
[ Dolg_K ] [ nvarchar ] ( 150 ) COLLATE Cyrillic_General_CI_AS NULL , название должности для карточки
[ K_go ] [ nvarchar ] ( 150 ) COLLATE Cyrillic_General_CI_AS NULL , название должности — кого
[ K_mu ] [ nvarchar ] ( 150 ) COLLATE Cyrillic_General_CI_AS NULL , название должности — кому
[ K_m ] [ nvarchar ] ( 150 ) COLLATE Cyrillic_General_CI_AS NULL название должности — ким
[ arh ] [ int ] NOT NULL признак записи в архиве 0 или 1
) ON [ PRIMARY ]
как видно, в целом справочники похожи — они отличаются только количеством текстовых полей, которые записываются и читаются в БД, т.е. три поля во всех справочниках однотипны — это поля id (Kod), Kod*, arh — первые два — числовые значения, последнее — может содержать либо 0 либо 1. Поле id автоинкремент — т.е. поле ввода ему не нужно, оно может только отображаться. Хотя бывают задачи, когда нужно иметь возможность устанавливать его вручную, тогда нужно реализовывать отдельную операцию — но в данном случае нет такой необходимости. Поле Kod пользователь должен иметь возможность устанавливать руками — т.е. для него мы предусматриваем отдельное текстовое поле ввода. Для поля arh нам достаточно чекбокса — так как оно может иметь только два значения. И как минимум, в каждом справочнике должно быть хотя бы одно текстовое поле. Структура конечно так себе, тут ничего не скажешь. Человек который ее проектировал — сложной судьбы человек, мягко говоря. 🙂 Но тут я не буду останавливаться на принципах проектирования БД, скажу только, что если вы реализуете подобное — старайтесь соблюдать единообразие. Если во всех справочниках присутствует однотипные поля — используйте для них и одинаковые названия. Не должно в одной из таблиц ключевое поле в одном случае Kod а во втором id. Не усложняйте сами себе жизнь.
Что бы нормально работать со справочниками — я бы рекомендовал добавить в БД две дополнительные таблицы, задача которых — хранить метаданные для отображения. В первой из них храните идентификатор справочника, название таблицы справочника, возможно название справочника для отображения (если система одноязычная, либо название для языка по умолчанию) и другие параметры, которые возможно вам понадобятся, а во второй таблице соответственно идентификатор записи, идентификатор справочника, имя поля и название поля для отображения. Ну и другие параметры, которые помогут вам настраивать отображение каждого из полей.Таблицы естественно должны быть связаны по идентификатору справочника. Если вы сердцем чуете что естественные ключи лучше чем искусственные — можете использовать в качестве ключа название таблицы справочника. Это на любителя.
В таком случае для каждого справочника задача упрощается максимально. После того, как таблицы созданы и заполнены — следующий шаг — создание основной формы. Помните, выше мы говорили о контроллере — так вот проще всего делать это через него. Если же эта модель вам кажется слишком сложной — то можно обойтись и без этого. В первую очередь определяемся — как будет происходить загрузка наших данных. Так как справочников может быть один и больше — используем TPageControl. Располагаем его на форме, называем pcMain, настраиваем нужные параметры. В принципе ничего особо сложного в этом нет — поэтому все дальнейшее я буду иллюстрировать кодом.
Код основной формы:
#include
#pragma hdrstop
#include «mainfm.h»
#include «addedit.h»
//—————————————————————————
#pragma package(smart_init)
#pragma resource «*.dfm»
TfmMain * fmMain ;
//—————————————————————————
__fastcall TfmMain :: TfmMain ( TComponent * Owner )
: TForm ( Owner ) ,dmMain ( Owner )
{
//тут пишете код, в котором инициализируете подключение к БД. Если БД уже подключена — используется другой конструктор
}
__fastcall TfmMain :: TfmMain ( TComponent * Owner, TADOConnection * db )
: TForm ( Owner ) ,dmMain ( Owner,db )
{
dmMain — > loadPages ( this — > pgMain ) ;
dmMain — > loadReference ( getCurrentGrid ( ) ) ;
}
//—————————————————————————
TDBGrid * __fastcall TfmMain :: getCurrentGrid ( )
{
if ( pgMain — > ActivePageIndex == — 1 ) return ;
TDBGrid * db = NULL ;
for ( int i = 0 ; i < this - >ComponentCount ; ++ i ) {
if ( this — > Components — > ClassName ( ) ! = «TDBGrid» ) continue ;
db = dynamic_cast < "TDBGrid" >( this — > Components ) ;
if ( db — > Parent == pgMain — > ActivePage ) break ;
}
return db ;
}
void __fastcall TfmMain :: pgMainChange ( TObject * Sender )
{
dmMain — > loadReference ( getCurrentGrid ( ) ) ;
}
//—————————————————————————
void __fastcall TfmMain :: FormDblClick ( TObject * Sender )
{
TStringList * ls ;
TfmAddEdit * fm ;
try {
fm = new TfmAddEdit ( NULL ) ;
//получаем перевичный ключ
fm — > id = dmMain — > adoQuery — > Fields — > FieldByNumber ( 0 ) — > AsInteger ;
//тут получаем параметры наших полей из доптаблицы в список
ls = new TStringList ;
dmMain — > loadReferenceFields ( ls ) ;
//тут обрабатываем наш список — как создавать объекты и инициализировать их параметры
// показано выше. не забывайте проверять высоту формы и высоту объектов
.
}
__finally {
if ( fm ) delete fm ;
if ( ls ) delete ls ;
}
//—————————————————————————
class TdmMain : public TDataModule
{
__published : // IDE-managed Components
TADOConnection * adoConnect ;
TADOQuery * adoQuery ;
TDataSource * dsQuery ;
TADOQuery * adoExecute ;
private : // User declarations
public : // User declarations
__fastcall TdmMain ( TComponent * Owner ) ;
__fastcall TdmMain ( TComponent * Owner, TADOConnection * db ) ;
void __fastcall loadPages ( TPageControl * pg, const int index = 0 ) ;
void __fastcall loadReference ( TDBGrid * gb ) ;
void __fastcall loadReferenceFields ( TStrings * ls ) ;
} ;
//—————————————————————————
extern PACKAGE TdmMain * dmMain ;
//—————————————————————————
#endif
//—————————————————————————
#include
#pragma hdrstop
}
void __fastcall TdmMain :: loadPages ( TPageControl * pg, const int index )
{
TTabSheet * tab ;
adoExecute — > SQL — > LoadFromFile ( «loadreferense.sql» ) ;
adoExecute — > Active = true ;
while ( ! adoExecute — > Eof ) {
tab = new TTabSheet ( pg ) ;
tab — > Name = adoExecute — > FieldByName ( «tablename» ) — > AsString ;
//так же настраиваем другие параметры если надо
TDBGrid * grid = new TDBGrid ( tab ) ;
grid — > Name = «gd» + tab — > Name ;
grid — > Parent = tab ;
grid — > Tag = adoExecute — > FieldByName ( «referenceid» ) — > AsInteger ;
grid — > Align = alClient ;
grid — > OnDblClick = fmMain — > OnDblClick ; //устанавливаем обработчик двойного клика
adoExecute — > Next ( ) ;
}
if ( pg — > PageCount > index ) pg — > ActivePageIndex = index ;
else pg — > ActivePageIndex = 0 ;
}
void __fastcall TdmMain :: loadReference ( TDBGrid * gb )
{
if ( ! gb ) return ;
adoQuery — > Active = false ;
adoQuery — > LoadFromFile ( gb — > Name + «.sql» ) ;
adoQuery — > Active = true ;
gb — > DataSource = dsQuery ;
}
//—————————————————————————
Как видно в коде, практически все компоненты создаются динамически, и в процессе работы я им присваиваю необходимые обработчики. Значительная часть кода опущена, так как она строится по тем же принципам, что и приведенный. Естественно в модуле данных надо реализовать сохранение изменений и т.п., но я думаю что вы с этим сможете справится сами. Ничего сложного. Кроме того — если вы обратили внимание — запросы к БД загружаются из файлов. Я считаю подобный подход более практичным — когда запросы хранятся отдельно от приложения. Хотя конечно все еще зависит от конкретных задач и от ваших предпочтений.
Надеюсь что этот материал оказался полезным — если есть вопросы, задавайте в комментариях.
Как сделать справочник на c
Добрый день, уважаемые форумчане!
Я реализую программу «Телефонный справочник».
Проблема возникает при считывании данных с консоли в поля структуры.
Хотелось бы, чтобы данные для каждого поля считывались как цельная строка, которая в дальнейшем приводилась к типу char[] / char*
Заранее благодарю за помощь.
#include "stdio.h" #include "iostream" #include "string.h" using namespace std; struct Persone < char *firstname; char *lastname; char *callnumber; Persone *next, *head; >; void Delete (Persone *Pers) < if (Pers ->head == NULL) < cout if (Pers -> head != NULL)/Если ввести в цикл while, то это будет реализацией очистки списка //Данный алгоритм я реализовал в методе Clear_List(); Persone *show_delete_element;//напоследок сохраним удаляемый show_delete_element = Pers-> head; //элемент для показа в консоли Persone *Temp_stack = Pers -> head -> next; // сохраняем ссылку на следующий элемент cout firstname lastname callnumber head; Pers -> head = Temp_stack;//голова стека указывает на следующий элемент cout > void addElem (char *firstname, char *lastname, char *callnumber, Persone *&pers) < Persone *temp = new Persone; temp ->firstname = firstname; temp -> lastname = lastname; temp -> callnumber = callnumber; //реализация стека temp -> next = pers -> head; pers -> head = temp; > char *Get_Data (string &sstr) < char* cstr2 = new char[sstr.length()]; strcpy(cstr2, sstr.c_str()); for (int i = 0; i < sstr.length(); i++) cout void Show (Persone *per) < Persone *List = per ->head; while (List != NULL) < cout firstname lastname callnumber next; > if (per->head == NULL) < cout > void Input (Persone *&pers) < string f_n, l_n, c_n; cout void Menu () < cout void ClearList (Persone *per) < while (per ->head != NULL) < Persone *temp = per ->head -> next; delete per->head; per->head = temp; > > int main () < setlocale (LC_ALL, "russian"); //system ("color f2"); Persone *pers = new Persone; pers->head = NULL; cout
| DimitryLutsenko |
| Посмотреть профиль |
| Найти ещё сообщения от DimitryLutsenko |