Components for Delphi and C++ Builder.

Перейти в английский форум
Перейти на EhLib.com
Текущее время: 29 мар 2024, 06:19

Часовой пояс: UTC




Начать новую тему Ответить на тему  [ Сообщений: 9 ] 
Автор Сообщение
СообщениеДобавлено: 29 мар 2018, 14:08 
Не в сети

Зарегистрирован: 23 мар 2017, 13:41
Сообщений: 70
Здравствуйте, при срабатывании события OnChange столбца из TMemTableEh мне нужно пройтись по данным таблицы и произвести условный подсчет.
Но так как двигать курсор в данном случае вообще не вариант, я обхожу коллекцию с помощью вьюшки:

Код:
procedure TForm11.mtDataOnChange(Sender: TField);
var i, n : integer;
begin
    n := 0;
    for i := 0 to mtData.RecordsView.MemTableData.RecordsList.Count-1 do begin
        with mtData.RecordsView.MemTableData.RecordsList[i] do begin
            n := n + DataValues['F1', dvvCurValueEh];
        end;
    end;
end;


И вот все круто, но я не могу получить измененное значение таким образом, мне возвращается старое значение.
По идее я должен был получить 200+100, а получил 200+300.

Код:
DataValues['F1', dvvCurValueEh]
пробовал вызывать с разными параметрами:
Код:
dvvOldValueEh, dvvCurValueEh, dvvEditValueEh, dvvValueEh,
    dvvOldestValue, dvvRefreshValue


Что я делаю не так?

UPD: Полный код для наглядности
Код:
function TForm11.GetValue(valVer: TDataValueVersionEh):string;
begin
    try
        result := VarToStr(mtData.RecView.Rec.DataValues['F1', valVer]);
    except on ex:Exception do
        result := ex.Message;
    end;
end;

procedure TForm11.mtDataOnChange(Sender: TField);
var i, n : integer;
begin
    label7.Caption  := GetValue(dvvOldValueEh);
    label8.Caption  := GetValue(dvvCurValueEh);
    label9.Caption  := GetValue(dvvEditValueEh);
    label10.Caption := GetValue(dvvValueEh);
    label11.Caption := GetValue(dvvOldestValue);
    label12.Caption := GetValue(dvvRefreshValue);

    label13.Caption := mtData.FieldByName('F1').AsString;

    n := 0;
    for i := 0 to mtData.RecordsView.MemTableData.RecordsList.Count-1 do begin
        with mtData.RecordsView.MemTableData.RecordsList[i] do begin
            n := n + DataValues['F1', dvvCurValueEh];
        end;
    end;

    Label15.Caption := 'Текущее значение: '+IntToStr(n)+', а ну нужно получить: 300';
end;

procedure TForm11.FormShow(Sender: TObject);
begin
    mtData.FieldDefList.Clear();
    mtData.FieldDefs.Add('F1', ftInteger, 0, false);
    mtData.CreateDataSet();

    mtData.AppendRecord([200]);
    mtData.AppendRecord([300]);

    mtData.FieldByName('F1').OnChange := mtDataOnChange;

    mtData.Edit();
    mtData.FieldByName('F1').Value := 100;
    mtData.Post();
end;


Вложения:
mtRec.PNG
mtRec.PNG [ 7.14 KiB | Просмотров: 1183 ]
memRec.rar [51.78 KiB]
Скачиваний: 62
Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 09 апр 2018, 09:46 
Не в сети

Зарегистрирован: 23 мар 2017, 13:41
Сообщений: 70
Почему разработчики ничего не отвечают? за 60000 в год, хотелось бы больше интерактивности.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 09 апр 2018, 10:51 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1546
Добрый день.

Извините за задержку.
Используйте вот такой вариант доступа к данным.

Код:
    n1 := 0;
    for i := 0 to mtData.InstantReadRowCount-1 do
    begin
      mtData.InstantReadEnter(i);
      n1 := n1 + mtData.FieldByName('F1').AsInteger;
      mtData.InstantReadLeave;
    end;

    Label16.Caption := 'Текущее значение: '+IntToStr(n1)+', а ну нужно получить: 300';



Цитата:
"EhLib - Руководство разработчика.doc"
Быстрый доступ к значениям записи
- Использовать методы InstantReadEnter, InstantReadLeave для перехода в режим InstantRead. InstantReadEnter входит в режим просмотра записей и переходит на запись в DataSet’е, определенную параметром RowNum. После этого можно читать значения записи. Каждому вызову метода InstantReadEnter, должен соответствовать вызов InstantReadLeave для выхода из режима чтения записей. В режиме InstantRead нельзя менять значения полей записи. Методы InstantReadEnter, InstantReadLeave не посылают события об изменении позиции записи внешним компонентам.

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 09 апр 2018, 18:28 
Не в сети

Зарегистрирован: 23 мар 2017, 13:41
Сообщений: 70
спасибо


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 13 дек 2018, 14:15 
Не в сети

Зарегистрирован: 23 мар 2017, 13:41
Сообщений: 70
Хотелось бы продолжить данную тему, так как проблема все таки имеет место и не решается с помощью выше указанного способа.

И так начнем, у нас есть источник данных в виде TMemTableEh и есть древовидная структура таблицы.
Есть ветки, которые пользователь может свернуть.
Так вот, когда пользователь вводит некие данные, нам нужно подсчитать некий итог, и тут начинаются пляски с бубном.
Предоставленные способы обхода данных TMemTableEh не дают нужного результата.

Полный пример реализующий данную проблему доступен в прикрепленном проекте.

Если есть какой-то другой способ - хотелось бы его узнать, в документации ничего такого не нашел (вполне возможно что плохо смотрел).

Способ первый: через InstantReadEnter - не заходит в свернутые ветки
Код:
// При этом варианте не учитываются свернутые ветки
for i := 0 to mtData.InstantReadRowCount-1 do begin
    mtData.InstantReadEnter(i);
    if mtData.FieldByName('F2').AsInteger > 0 then
        total := total + mtData.FieldByName('F3').AsInteger;
    mtData.InstantReadLeave;
end;

Способ второй: через RecordsView.MemTableData.RecordsList - не видит измененные данные
Код:
// При этом варианте не учитываются измененное значение F3 текущей записи.
for i := 0 to mtData.RecordsView.MemTableData.RecordsList.Count-1 do begin
    with mtData.RecordsView.MemTableData.RecordsList[i] do begin
        if (DataValues['F2', dvvCurValueEh] > 0) then begin
            total := total + DataValues['F3', dvvCurValueEh];
        end;
    end;
end;


Способ третий: свой способ (но кривой)
Так же минус этого способа в том, что необходимо либо помнить длиннющие пути, либо копировать от куда-то шаблоны,
а это очень влияет на производительность при написании кода.
Код:
// И вот такой более менее рабочий вариант
// Проблема этого метода в том, что не получается сделать метод расширения
// для обхода коллекции, так как я не знаю как сопоставить текущую запись вьюшки и курсора
// без явного указания полей
for i := 0 to mtData.RecordsView.MemTableData.RecordsList.Count-1 do begin
    with mtData.RecordsView.MemTableData.RecordsList[i] do begin
        if (DataValues['F2', dvvCurValueEh] > 0) then begin
            // По текущей записи берем через курсор, а остальные из вьюшки
            if DataValues['F1', dvvCurValueEh] = mtData.FieldByName('F1').AsInteger then
                total := total + mtData.FieldByName('F3').AsInteger
            else
                total := total + DataValues['F3', dvvCurValueEh];
        end;
    end;
end;


Что бы хотелось в итоге - рабочий нормальный незамысловатый вариант, либо что-то на подобии такого
Код:
mtData.ForeachView(procedure (Rec: TViewRecordEh) begin
     ShowMessage(Rec.FieldByName('F3').AsString);
     if (Rec.FieldByName('F1').AsInteger = 5) then
         Rec.Break();
end);


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


Вложения:
MemTableForEachBug.rar [2.38 KiB]
Скачиваний: 41
step_1.PNG
step_1.PNG [ 28.32 KiB | Просмотров: 813 ]
Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 18 дек 2018, 21:37 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1546
Добрый день.

При обращении через способ 2 - "через RecordsView.MemTableData.RecordsList"
Используйте вместо константы dvvCurValueEh константу dvvValueEh.
По константе dvvCurValueEh возвращается текущее значение без учета буфера редактирумых (Edit-Post)значений.

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 19 дек 2018, 06:34 
Не в сети

Зарегистрирован: 23 мар 2017, 13:41
Сообщений: 70
Спасибо, видать меня ввело в заблуждение то, что я проверял вот так вот (это из первого поста).
Код:
mtData.RecView.Rec.DataValues['F1', dvvValueEh]
,
при этом мне возвращалось значение которое было до редактирования,
и я подумал что тоже самое будет и для обхода всей коллекции.


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 19 дек 2018, 08:00 
Не в сети

Зарегистрирован: 23 мар 2017, 13:41
Сообщений: 70
Подскажите еще одни момент, имеет ли право на существование подобный код?
Код:
for i := 0 to mtData.RecordsView.MemTableData.RecordsList.Count-1 do begin
    mtData.InstantReadEnter(mtData.RecordsView.MemTableData.RecordsList[i], i);
    try
        v := mtData.FieldByName('F3').AsInteger;
        total := total + v;
    finally
        mtData.InstantReadLeave();
    end;
end;


потому как сейчас он у меня падает на InstantReadEnter, когда я выхожу за рамки отфильтрованных записей.
Например у меня есть всего 8 записей, 2 из них скрыты в дереве, итого 6 записей, так вот по 6 записях он проходит нормально, и получает корректные значения, а при попытке доступа к записи, которая не скрыта но по индексу находится за пределами видимых записей - получаю ошибку.
Код:
0 => 0 (visible)
1 => 20 (hiden)
2 => 30 (hiden)
3 => 0 (visible)
4 => 50 (visible)
5 => 55 (visible)
6 => Exception

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


Вернуться наверх
 Профиль  
 
СообщениеДобавлено: 19 дек 2018, 12:28 
Не в сети

Зарегистрирован: 23 мар 2017, 13:41
Сообщений: 70
разобрался, достаточно было вторым параметром передать 0
вместо
Код:
mtData.InstantReadEnter(mtData.RecordsView.MemTableData.RecordsList[i], i);

можно так
Код:
mtData.InstantReadEnter(mtData.RecordsView.MemTableData.RecordsList[i], 0);


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Часовой пояс: UTC


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB