Здравствуйте, возник вопрос по MemoryDataset - есть ли возможность непосредственно в коде добавить в него столбцы для данных? И как (тоже в коде) выводить эти столбцы в грид?

Нравится

3 комментария
var DataField = AddStringDataField(Mds.DataFields, 'Name' + i, 'Заголовок колонки', 100);
DataField.Tag = 'UniversalReport' + i;
AddGridColumnsByDataset(dgvMain, Mds, false);
Mds.Close();
Mds.Open();

Отлично, колонки вроде добавляет.

['Name' + i] - это имя столбца в MemoryDataset-е, который потом можно заполнить на AfterOpen? И как его очистить при очередном изменении числа колонок (ругается что дублируется свойство Name в AddStringDataField)?

Перед каждым выполнением конечно нужно эти столбцы чистить:

Mds.DataFields.Clear();

А в остальном вы правы.
Единственное, на AfterOpen() лично я обращался не по имени, а по порядку:

Dataset.DataFields.Items(k).Value = 'SomeValue';
Показать все комментарии

Добрый день!
Почему-то не не обновляется объект IDataGrid.
Смотрю ActiveView.Items(1).DataField.DisplayValue там одно значение, а реально на экране совсем другое. Особенность грида в том что в DatasetLink указан редактируемый MemoryDataset, в котором так же установлено нормальное значение.
Обновляться прекращает после того как в форме нажимаешь ОК (не важно редактировался ли MemoryDataset). После чего всегда визуально отображается содержимое формы по которой был клик ОК, не смотря на то что открывается совсем другое содержимое...

Нравится

16 комментариев

Ммм, обращаться к активной (текущей выделенной) строке нужно так:

DataGrid.DatasetLink.Dataset.DataFields('ID').Value;

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

"Олейник Дмитрий" написал:Ммм, обращаться к активной (текущей выделенной) строке нужно так:

DataGrid.DatasetLink.Dataset.DataFields('ID').Value;

Дмитрий, добрый день! Возможно я "ммм" не очень понятно пишу, но еще раз подчеркну

"AlexLS" написал:в DatasetLink указан редактируемый MemoryDataset, в котором так же установлено нормальное значение

"Олейник Дмитрий" написал:при выходе из режима редактирования ячейки

никакого редактирования не происходило, только открытие формы в которой в датасете и в гриде дебаггер показывает правильные значения а "глаза" видят значения из той формы в которой последний раз был апдейт/инсерт!

Алекс, добрый день.

Все еще не понял про "нормальные значения".

Ни разу не сталкивался с таким поведением. Грид не кеширует значения датасета. Мне кажется чтото не так с датасетом, привязанным к гриду, вернее скорее всего датасет, в котором корректные значения не привязан к гриду. Можете написать кейс воспроизведения, при котором грид визуально отображает данные старой (насколько я понял) формы?
Я также, желательно, приведите код заполнения memoryDataset'a.

В GridAreaOnPrepare пишу:

if (Assigned(ParentDataset = GetAttribute(Window, 'ParentDataset'))	) 
  if (!IsEmptyValue(IsInserting = ParentDataset.State == dstInsert)) {
    var ds = Services.GetNewItemByUSI(IsInserting ? 
                'ds_RequestStockTypeMec' : 'ds_TypeMecDetail');
      if(!IsInserting) 
        ApplyDatasetFilter(ds, 'RequestStock2ID', ParentDataset('ID'),true);
      ds.Close();
      ds.Open();
      mdsTypeMecDetail.Dataset.Close();
      CopyMemoryDataset(ds, mdsTypeMecDetail.Dataset);
      if (Assigned(grdData))
      if(grdData.DatasetLink.Name != 'mdsTypeMecDetail')
      grdData.DatasetLink = mdsTypeMecDetail;
      ds.Close();
 
  }

где ds_TypeMecDetail - штатный датасет для данной детали,
ds_RequestStockTypeMec - датасет справочника, из которого подгружаются данные при Append
mdsTypeMecDetail - собственно меморидатасет, который и нужно заполнять в карточке
ParentDataset - датасет карточки редактирования записи, в которой и находится windowcontainer с гридом.

Проблема скорее всего тут:

grdData.DatasetLink = mdsTypeMecDetail;

Лучше всего сначала очистить, а затем заполнить свойство DatasetLink:

grdData.DatasetLink = System.EmptyValue;
grdData.DatasetLink = mdsTypeMecDetail;

А затем нужно открыть mds:

grdData.DatasetLink = System.EmptyValue;
grdData.DatasetLink = mdsTypeMecDetail;
grdData.DatasetLink.Dataset.Open();

И определить событие для DatasetLink(mdsTypeMecDetail): OnDatasetAfterOpen(Dataset), и уже внутри него заполнять mds. Тогда все будет корректно.

function dlDataOnDatasetAfterOpen(Dataset) {
Dataset.Append();
....
Dataset.Post();
}

Также не понял, почему используется GridAreaOnPrepare... Но тут нужно знать вашу бизнес задачу.

"Олейник Дмитрий" написал:Также не понял, почему используется GridAreaOnPrepare... Но тут нужно знать вашу бизнес задачу.

Исходно нужно реализовать "множественный выбор" (то есть все значения из справочника с галочками... очень похоже на деталь Доступ :smile: только в карточке редактирования).
Уже работающую деталь потребовалось положить в эдитвиндоу. Пытался "малой кровью" эту деталь использовать с подменой обычного датасета на меморидатасет.

Ага, я когда-то чтото подобное делал с напоминаниями: открывается каточка детали "напоминания" какого либо раздела, там есть лукапное поле контакт, жмем на лупу и открывается multi_select_window - можно выбрать несоклько контактов, а затем при закрытии краточки - на деталь добавлялось столько записей, сколько выбрано было контактов.
Посмотрите, может быть поможет:

http://www.community.terrasoft.ru/blogs/8462

Здорово получается, до инсерта/апдейта

grdData.DatasetLink.Dataset.Open();

вызывает memoryDatasetOnDatasetAfterOpen
а после апдейта .Open() уже игнорирует AfterOpen!

[quote="Олейник Дмитрий"]Ага, я когда-то чтото подобное делал с напоминаниями: открывается каточка детали "напоминания" какого либо раздела, там есть лукапное поле контакт, жмем на лупу и открывается multi_select_window - можно выбрать несоклько контактов, а затем при закрытии краточки - на деталь добавлялось столько записей, сколько выбрано было контактов.
Посмотрите, может быть поможет:

http://www.community.terrasoft.ru/blogs/8462[/quote]
Спасибо, Дмитрий! Попробую поразбираться.

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

Alex, а что значит Update?

Немного про мемориDS: это штука живет от Open() до Close(); Заполняется на OnDatasetAfterOpen(); После открытия датасета, можно позиционироваться на любой строке,и изменять любую ячейку:
Dataset.Edit();
Dataset.Post();
Все изменения грид перерисует самостоятельно.
Помните, что каждый рефреш, (Dataset.Close(), Dataset.Open()) вызывает перезаполнение датасета. Т.е. если вы не сохранили измененные данные куда то в таблицу БД, с которой заполняете датасет, то он заполнится старыми значениями.

"Олейник Дмитрий" написал:

Alex, а что значит Update?

Немного про мемориDS: это штука живет от Open() до Close(); Заполняется на OnDatasetAfterOpen(); После открытия датасета, можно позиционироваться на любой строке,и изменять любую ячейку:

Dataset.Edit();

Dataset.Post();

Все изменения грид перерисует самостоятельно.

Помните, что каждый рефреш, (Dataset.Close(), Dataset.Open()) вызывает перезаполнение датасета. Т.е. если вы не сохранили измененные данные куда то в таблицу БД, с которой заполняете датасет, то он заполнится старыми значениями.

С уважением,

Олейник Дмитрий


В какой-то момент меморидатасет перестает реагировать на Dataset.Close() и Dataset.Open().
Пишу

grdData.DatasetLink = System.EmptyValue;
grdData.DatasetLink = mdsRStock2AccDivision;
grdData.DatasetLink.Dataset.Close();
SetAttribute(grdData.DatasetLink.Dataset, 'ParentWindow', Window);
if (Assigned(ParentDataset = GetAttribute(Window, 'ParentDataset'))	)		SetAttribute(grdData.DatasetLink.Dataset, 'ParentDataset', ParentDataset);
grdData.DatasetLink.Dataset.Open();

но ни
function mds_RStock2AccDivisionOnDatasetAfterOpen
ни
function mds_RStock2AccDivisionOnDatasetAfterClose

не срабатывают!

наконец нашел свой косяк:
в посте (записи из мемдатасета в реальный датасет) для мемдатасета делал DisableEvents(), а EnableEvents() забыл сделать.... теперь все обновляется!

Только почему-то если

Dataset.EnableEvents();
Dataset.Close();

то возникает ошибка:

TSObjectLibrary.MemoryDataset: Cannot focus a disabled or invisible window

а

Dataset.Close();
Dataset.EnableEvents();

ошибку не вызывает

Проверьте состояние датасета в момент Open() - быть может он уже в состоянии Open(), тогда функция не вызывается и события AfterOpen() не тригернутся.

Alex, да, бывает :)

"Олейник Дмитрий" написал:

Alex, да, бывает :)

С уважением,

Олейник Дмитрий


Дмитрий, спасибо Вам за помощь!

Показать все комментарии

Суть проблемы такова:
DataGrid привязан к MemoryDataset , в котором сейчас около 60 записей.
Возможно ли сделать вывод в DataGrid по 20 или 40 записей на страницу ?

Нравится

7 комментариев

Добрый день!

Если насильно установить ТОР не получиться получить удовлетворительные результаты, то никак. Количество записей устанавливается только в одном месте, а затем считывается во всех гридах.

Здравствуйте!

У MemoryDataset, как и у обычного, есть свойство FetchRecordsCount. Подробнее в Terrasoft SDK:

http://www.terrasoft.ua/sdk/!!MEMBEROVERVIEW_IMemoryDataset.html

таким образом, для реализации постраничности набора данных следует установить данное свойство в 20 (40) записей:

   MemoryDataset.FetchRecordsCount = 40;
   RefreshDataset(MemoryDataset);

"Alimova Anna" написал:У MemoryDataset, как и у обычного, есть свойство FetchRecordsCount.

Кстати, да :)

это все хорошо, только у меня почему-то
FetchRecordsCount =-1 всегда

.. я же MemoryDataset заполняю вручную
причем при RefreshDataset(MemDataset) все обнуляется )))

Попробуйте FetchRecordsCount указать при инициализации датасета.

все-равно не получается.
DataGrid у меня привязан на dlData (в качестве Датасета тут - MemoryDataset)

Причем установить "FetchRecordsCount" для dlData или MemoryDataset - не получается =)

Пока самый худший вариант решения для меня - это записывать все в базу, а потом уже выбирать от туда с "TOP 20" !?

Добрый день!

И все-таки никак :smile:

У MemoryDataset нет возможности перехода между страницами.
Поэтому если необходимо выводить данные частями с использованием MemoryDataset'ов, то необходимо их создавать несколько.

Показать все комментарии

Добрый день!
Суть дела такова: каким образом связать в FastReport Dataset и MemoryDataset? C двумя Dataset'ами - все понятно, ну а с MemoryDataset - вопрос, так как он заполняется не из select query. Или все же связь будет, если и там и там будет поле одинакового названия, например, ds_A.ID и mds_B.ID?

Нравится

5 комментариев

Здравствуйте.

От обычного датасета MemoryDataset отличается лишь тем, что у него нет SelectQuery, он не работает с базой вообще и может лишь хранить список записей (не постранично), и позволять вставку, редактирование, удаление и навигацию по записям. Заполнять датасет лучше всего в обработчике его события OnDatasetAfterOpen. Это значит, выполнять нужное количество раз операции:

Dataset.Append();
Dataset.Values('MyField') = MyValue;
Dataset.Post();

Такой датасет можно использовать в отчете, но при использовании его как DetailData Dataset, вам нужно каждый раз на OnDatsetAfterOpen заполнять вручную теми данными, которые являются "дочерними" для MasterData.

Также рекомендую ознакомится со следующей темами: http://www.community.terrasoft.ua/forum/topic/1630
http://www.community.terrasoft.ua/forum/topic/1312

Спасибо, Дмитрий, за ответ. Тему http://www.community.terrasoft.ua/forum/topic/1630 я уже видел, мне подобный способ не подходит. Этот вопрос был задан для реализации такого функционала http://www.community.terrasoft.ua/forum/topic/8365, а с помощью компонента DBCrossTab я не вижу возможности добиться подобной гибкости.

Constantine, в таком случае нужно вручную в коде заполнять MDS теми данными, которые бы мы получили в обычном Dataset'e c помощью sq, со включенным фильтром сравнения tbl_ChildTable.ParentID = :Parameter ParentID.

"Олейник Дмитрий" написал:в таком случае нужно вручную в коде заполнять MDS теми данными, которые бы мы получили в обычном Dataset'e c помощью sq, со включенным фильтром сравнения tbl_ChildTable.ParentID = :Parameter ParentID.

это все понятно, но как связать MasterData и DetailData? у них у обоих есть поле ID, в которых хранятся равные значения для связи, но как системе указать, что связывать их нужно именно по этим полям? на данный момент, как только я после MasterData ставлю DetailData, никаких данных не выводится вообще

Здравствуйте.

Master и Detail Data связываются указанием для Detail Data свойства MasterData. Для Master Data и Detail Data также привязываются датасеты (главный и подчиненный соответственно). Для того, чтобы в Detail Data была отображена только та информация, которая является подчиненной по какому либо признаку по отношению к Master Data, в сервисе Select query мы включаем фильтр сравнения, по какому либо полю таблицы, которое будет сравниваться с значением первичного ключа (ID) главного датасета.
Соответственно, в Detail Data, датасетом которой является MDS, такой фильтр включить не получится, именно потому, для корректного построения отчета, необходимо вручную заполнять его теми данными, которые будут уже отфильтрованы по полю внешнего ключа (т.е по первичному полю для главного датасета).

Показать все комментарии

В случае если в MemoryDataset'e используется сортировка, то при сохранении записи, если изменение повлекло изменение порядка происходит "внутренняя сортировка", т.е. происходит сортировка записей всего грида/датасета, а перерисовывается только текущая строчка грида и в ней одной отображаются корректные данные.
Каким образом можно обойти данную проблему.
Может можно отключить автоматическую сортировку перед сохранением.
Или волшебная команда типа grdData.Repaint (пробовал, не помогло).
Или может есть бинарные файлы с корректной работой этой связки, у нас версия 3.3.2.203.
Помогите уважаемые гуру!

Нравится

6 комментариев

Здравствуйте Валерий,
Пытался воспроизвести данную проблему, возникили вопросы.
Как вы заполняете MemoryDataset ?
Выводится ли все корректно если сделать обновление реестра?

Вышлите пожалуйста сервисы, в вашем варианте.

Здравствуйте, Алексей!
Прикрепляю файл с отредактированными сервисами.
При запуске после добавление нескольких строк ->Сортировка -> редактирование даты, которое приводит к изменению порядка строк и проблема воспроизведется.
..\Bin\TSClient.exe /wnd=wnd_mdsvihGridArea1

MemoryDataset заполняется либо через dlData.Dataset.Append(), затем исправляется дата на необходимую.
Если предварительно сделать обновление реестра , то проблема исчезает.

Но обновлять реестр после каждого изменения это не серьезно.

В реестре после редактирования ячейки (после Post) происходит обновление текущей строки, но не предусмотрено, что из-за сортировки MemoryDataset сам изменит не только текущую, но и все остальные записи. Т.е. самым простым решением будет обновление датасета.
Но на самом деле хватило бы просто обновление реестра (без переоткрытия датасета). Поэтому в вашем случае можете применить обходное решение: на AfterPost делайте выключение/включение событий датасета. Выглядеть это будет так:

function dlDataOnDatasetAfterPost(Dataset) {
	Dataset.DisableEvents();
	Dataset.EnableEvents();
}

Спасибо!
Все заработало!

Показать все комментарии

При написании скрипт-контрола для мемори датасета столкнулся с неприятностью - курсор не двигался. Функция которая должна была обновить БД запускается с обработчика OnBeforeClose.

События включены,
Состояние dstBrowse,
кол. записей > 1,
После вызова GotoNext(), события BeforePositionChange и AfterPositionChange срабатывают,
В скрипте используется глобальный объект в котором храню ещё один инстанс этого же мемори датасета но с определяющим атрибутом при наличии которого скипаются обработчики событий. (Мне он нужен для сортировки в гриде).
Версия 3.2.2.3

Нравится

3 комментария

Ярослав, к сожалению, я ничего не понял что Вы хотите спросить, могли бы Вы написать более точнее?

Не работает GotoNext(), сообщений об ошибке нет, просто не переходит на следующую запись.

Прошу прощение за неясность:) сервисы я прикрепил

Проблема во включённых событиях, отключил - заработало.

Показать все комментарии

Версия 3.2.2.3
Есть проблемы с работой функции Locate MemoryDataset.
mds.Locate('ID', ID) - ошибка "Поле ID не найдено", хотя
mds.DataFields.ItemsByName('ID') - все есть.

Подскажите, пожалуйста, в чем может быть причина. Не хочется свой локейт писать.

Нравится

1 комментарий

Добрый день.

Спасибо за Ваш вопрос.

Для того, чтобы описаной выше проблемы не возникало, Вам необходимо сначала открыть dataset, например:

mds.Open();
mds.Locate('ID', ID);

С удовольствием ответим на все Ваши дополнительные вопросы.

Terrasoft Support Team

Показать все комментарии