AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 20.05.2010, 17:15   #1  
Serg is offline
Serg
Участник
 
116 / 30 (2) +++
Регистрация: 12.02.2002
Табличный процессор
Коллеги, кто-нибудь сталкивался с вопросом как устроен изнутри табличный процессор, как у него получается мгновенно вычислять достаточно большой объем данных? Может, есть ссылки, книги etc?
Старый 20.05.2010, 17:39   #2  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Уж не собираетесь ли Вы... Excel того... подвинуть плечом?!

А если серьезно, то в стародавние, почти былинные времена был у Борланда такой замечательный продукт, как Turbo Pascal. Так вот, в версии то ли в 6.0, то ли в 7.0 (а может и в обеих) были исходники демки табличного процессора. Напомню, что у этой фирмы был (есть?) свой собственный табличный процессор Quattro Pro. Так что они знавали толк в этом деле.
За это сообщение автора поблагодарили: Lemming (5).
Старый 20.05.2010, 18:42   #3  
AlexSD is offline
AlexSD
Microsoft Dynamics
Сотрудники Microsoft Dynamics
 
257 / 302 (11) ++++++
Регистрация: 14.10.2003
О чем идет речь? Какой табличный процессор? Какие объемы данных считаются достаточно большими?
Современные процессоры для настольных ПК могут выполнять десятки миллиардов операций в секунду http://www.intel.com/support/ru/proc.../cs-023143.htm. Сложить один миллиард чисел с другим миллиардом чисел может занять по времени меньше секунды.
Старый 20.05.2010, 21:46   #4  
Serg is offline
Serg
Участник
 
116 / 30 (2) +++
Регистрация: 12.02.2002
вопрос не просто в сложении чисел как таковом, а в их организации из реляционной модели в модель процессора, оперирования с ней и обратной конвертации.

ну те то что бы подвинуть, хотя бы прикинуть... что почем
Старый 21.05.2010, 08:59   #5  
AlexSD is offline
AlexSD
Microsoft Dynamics
Сотрудники Microsoft Dynamics
 
257 / 302 (11) ++++++
Регистрация: 14.10.2003
Если вы говорите о табличном процессоре, как понимаю, вы говорите об программах подбных Microsoft Excel? Если так, то причем здесь реляционная модель?
Если вспомнить устройство уже упомянутой программы входящей в комплект Turbo Pascal, то там в качестве внутренней структуры хранения данных в первых версиях использовался массив

X++:
const
  FXMax: Char  = 'G';  { Maximum number of columns in spread sheet   }
  FYMax        = 21;   { Maximum number of lines in spread sheet     }

type
  Anystring   = string[70];
  SheetIndex  = 'A'..'G';
  Attributes  = (Constant,Formula,Txt,OverWritten,Locked,Calculated);

{ The spreadsheet is made out of Cells every Cell is defined as      }
{ the following record:}

  CellRec    = record
    CellStatus: set of Attributes; { Status of cell (see type def.)  }
    Contents:   String[70];        { Contains a formula or some text }
    Value:      Real;              { Last calculated cell value      }
    DEC,FW:     0..20;             { Decimals and Cell Whith         }
  end;

 [B] Cells      =  array[SheetIndex,1..FYMax] of CellRec;[/B]
...
а потом, связанный список.
Старый 21.05.2010, 09:34   #6  
Serg is offline
Serg
Участник
 
116 / 30 (2) +++
Регистрация: 12.02.2002
Используем решение, в котором поженены ActiveX Excel и сама Axapta, часть вычислений делает ActiveX Excel и потом значение считываются и записываются в Axapta, порой это не так быстро как хотелось бы и достаточно сложно в настройках.
Старый 21.05.2010, 10:00   #7  
Zabr is offline
Zabr
Участник
Axapta Retail User
 
1,202 / 345 (14) ++++++
Регистрация: 26.06.2002
Адрес: Москва
Цитата:
Сообщение от Serg Посмотреть сообщение
Используем решение, в котором поженены ActiveX Excel и сама Axapta, часть вычислений делает ActiveX Excel и потом значение считываются и записываются в Axapta, порой это не так быстро как хотелось бы и достаточно сложно в настройках.
Это решение случайно не Axcision ? (Если так, то я бы на вашем месте подумал над установкой какой-нибудь более традиционной аналитической системы...)
Старый 21.05.2010, 10:55   #8  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Serg Посмотреть сообщение
потом значение считываются и записываются в Axapta, порой это не так быстро как хотелось бы
Об объёмах считывания какого порядка идёт речь? Сколько ячеек (строк, столбцов)?
Старый 21.05.2010, 12:16   #9  
Serg is offline
Serg
Участник
 
116 / 30 (2) +++
Регистрация: 12.02.2002
нет это не Axcision, называть не буду дыба не заниматься рекламой/антирекламой

Порядок примерно такой 150 строк*30 столбцов 4500 ячеек. Десятую часть из них вычисляет сам Excel т.е. около 450, считывание занимает в среднем секунд 5-10, т.е. гораздо дольше чем сам Excel считает и если нужно ввести 900 значений *5-10 секунд то полная обработка занимает около о 1часа - до 2,5 часов
Старый 21.05.2010, 12:26   #10  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Serg Посмотреть сообщение
Порядок примерно такой 150 строк*30 столбцов 4500 ячеек. Десятую часть из них вычисляет сам Excel т.е. около 450, считывание занимает в среднем секунд 5-10, т.е. гораздо дольше чем сам Excel считает и если нужно ввести 900 значений *5-10 секунд то полная обработка занимает около о 1часа - до 2,5 часов
Уфф... я пока почти не понимаю... давайте по порядку...

что вы чуть выше называете "ActiveX Excel"? OWC Spreadsheet или всё-таки большой "Microsoft Excel"?

что такое "считывание"? Аксапта читает из "Excel" или пользователь считывает с бумажки?

спрашиваю про пользователя, потому что тогда становится логичным "ввести (!) 900 значений", умноженное на "время считывания (!)"...
Старый 21.05.2010, 12:41   #11  
Serg is offline
Serg
Участник
 
116 / 30 (2) +++
Регистрация: 12.02.2002
речь о OWC Spreadsheet, пользовтаель в нем вводит данные, далее OWC Spreadsheet по формулам расчитывает показатели и их нужно считать т.е. просто activeCell = xExcelSheetManager.selected(Row, Сol) и записать в таблицу. Проблема еще в том, что нет данных какая имеено ячейка пересчиталсь и приходиться их считывать все;
Старый 21.05.2010, 13:35   #12  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Я бы воспользовался методом чтения из Excel (он подходит и для Spreadsheet), предложенным AndyD'ом здесь: Построчный импорт из Excel через COM . Скорость выполнения вас приятно удивит. Нужно будет скачать и зарегистрировать dll.

Что же касается того, как определить, что из ячеек изменилось (пересчиталось), то я бы воспользовался возможностью статического метода Set::difference, который может сравнить состав двух множеств и вернуть несовпадения (из первого множества). На псевдокоде это выглядит примерно так:
Код:
setРасхожденияПосле = Set::difference( setПослеОперации, setДоОперации );
Все множества - из контейнеров (а по физическому смыслу - ячеек) вида [строка,столбец,значение].

Перед грядущим изменением пробегаетесь по всем ячейкам и заполняете множество setДоОперации. После изменения опять пробегаетесь по всем ячейкам и заполняете множество setПослеОперации. Наконец, вычисляете множество setРасхожденияПосле (изменившиеся ячейки), которое затем циклом перебираете и записываете в нужную таблицу Аксапты (ну, или куда там вам надо).
Старый 21.05.2010, 14:22   #13  
Serg is offline
Serg
Участник
 
116 / 30 (2) +++
Регистрация: 12.02.2002
спасибо! попробуем.
Старый 21.05.2010, 16:58   #14  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Что ж, "утром - в газете, вечером - в куплете". Сваял я демонстрашку по этой задачке. Время сравнения двух множеств из заявленных 4500 элементов и перебора их расхождений у меня сплошь и рядом менее 1 секунды!

Перед запуском джоба необходимо зарегистрировать на компе упомянутую выше dll-ку AndyD'а (Построчный импорт из Excel через COM). После загрузки формы измените какие-нибудь ячейки (сотрите или замените иным текстом в ячейке). Закройте форму крестиком - в инфологе список расхождений. Имейте в виду, что время вывода в инфолог - "огромно" по сравнению с временем сравнения и перебора, поэтому оно и вынесено в отдельный цикл за пределы засечки по времени.
X++:
static void job_SpreadsheetAsTableProcessor(Args _args)
{
    Form                form = new Form();
    FormBuildDesign     formBuildDesign = form.addDesign('Design');
    Args                args = new Args();
    FormRun             formRun;
    FormActiveXControl  ss;

    COM                 SafeArray = new COM('AxSafeArray.SafeArray');
    COM                 range;
    COMVariant          cvRange;
    COMVariant          cvRow, cvCell;
    Array               arr;

    int                 rowCount, colCount;
    int                 row, col;
    str                 val;

    Set                 setBefore = new Set(Types::Container);
    Set                 setAfter  = new Set(Types::Container);
    Set                 setDiffer = new Set(Types::Container);
    SetEnumerator       enumr;

    int                 timeStart, timeDuration;
    ;

    // динамически генерируем форму
    args.object(form);

    formRun = classFactory.formRunClass(args);
    formRun.init();
    formRun.design().caption('Табличный процессор');

    ss = formRun.design().addControl(FormControlType::ActiveX, 'Spreadsheet');
    ss.className('{0002E541-0000-0000-C000-000000000046}');     // Microsoft Office Spreadsheet 10.0
    //ss.className('{0002E559-0000-0000-C000-000000000046}');   // Microsoft Office Spreadsheet 11.0

    ss.heightMode(FormHeight::ColumnHeight);
    ss.widthMode(FormWidth::ColumnWidth);

    range = ss.Range('A1:O300'); // 15 колонок - 300 строк
    range.Formula('="["&ROW()&","&COLUMN()&"]"'); // или, если будет ругаться, то: range.Formula('="["&СТРОКА()&","&СТОЛБЕЦ()&"]"');

    cvRange = range.Value2();

    rowCount = SafeArray.GetArrayRowCount(cvRange);
    colCount = SafeArray.GetArrayColCount(cvRange);

    // записываем состояние ячеек ДО изменения
    for (row=1; row<=rowCount; row++)
    {
        cvRow = SafeArray.GetArrayRow(cvRange, row);
        arr = cvRow.safeArray();
        for (col=1; col<=colCount; col++)
        {
            cvCell = arr.value(col);
            setBefore.add([row, col, cvCell.bStr()]);
        }
    }

    formRun.run();
    formRun.wait(); // здесь вручную изменяем несколько ячеек и закрываем форму крестиком

    timeStart = WinAPI::getTickCount();

    // записываем состояние ячеек ПОСЛЕ изменения
    cvRange = range.Value2();

    for (row=1; row<=rowCount; row++)
    {
        cvRow = SafeArray.GetArrayRow(cvRange, row);
        arr = cvRow.safeArray();
        for (col=1; col<=colCount; col++)
        {
            cvCell = arr.value(col);
            setAfter.add([row, col, cvCell.bStr()]);
        }
    }

    // находим расхождения в состояниях
    setDiffer = Set::difference( setAfter, setBefore );

    // "трогаем" все значения расхождений - как бы используем для каких-то наших целей
    enumr = setDiffer.getEnumerator();
    while (enumr.moveNext())
    {
        [row,col,val] = enumr.current();
    }

    timeDuration = WinAPI::getTickCount() - timeStart;
    info(strFmt('Сравнение и перебор расхождений выполнены за %1 миллисек.', timeDuration));

    setPrefix('Изменились следующие ячейки:');
    // отдельным циклом, чтобы исключить время вывода в инфолог
    enumr = setDiffer.getEnumerator();
    while (enumr.moveNext())
    {
        [row,col,val] = enumr.current();
        info(strFmt('Строка: %1 -- Столбец: %2 -- Новое значение: %3', row, col, val));
    }
}
Кстати, приложение "Переводчик" на сайте "ВКонтакте" переводит словосочетание "Табличный процессор" с русского на английский как "Spreadsheet". Я порадовался

P.S. А если фрагмент вывода в инфолог слегка изменить, то удобнее (по крайней мере, с точки зрения тестирования) будет вывести адрес ячейки вместо номеров строки и столбца:
X++:
    COM                 cells, cell;  // добавлено
    ...........
    setPrefix('Изменились следующие ячейки:');
    // отдельным циклом, чтобы исключить время вывода в инфолог
    cells = ss.Cells(); // добавлено
    enumr = setDiffer.getEnumerator();
    while (enumr.moveNext())
    {
        [row,col,val] = enumr.current();
        cell = cells.Item(row,col); // добавлено
        info(strFmt('Адрес: %1 -- Новое значение: %2', cell.Address(false,false), val)); // изменено
    }

Последний раз редактировалось Gustav; 21.05.2010 в 19:33.
За это сообщение автора поблагодарили: Serg (1), Poleax (1).
Старый 11.06.2010, 09:37   #15  
Serg is offline
Serg
Участник
 
116 / 30 (2) +++
Регистрация: 12.02.2002
а как задать range в формате RC...Все перепробывал и R1C1:R2C2, 1:1,2:2 и 1:1;2:2...?
Старый 11.06.2010, 11:01   #16  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Serg Посмотреть сообщение
а как задать range в формате RC...Все перепробывал и R1C1:R2C2, 1:1,2:2 и 1:1;2:2...?
А в Spreadsheet, по-моему, нотация R1C1 не поддерживается... А цель какая? Если нужно перебирать в цикле, то можно Range.Cells(i, j) использовать. А если формулу в диапазон вставить, то просто задаете формулу в нотации A1 для первой ячейки, т.е. как если бы только в одну ячейку вводили. При этом для других ячеек диапазона формула корректно настроится автоматически, например, Range("B1:B10").Formula = "=A1" даст формулу =А1 в ячейке B1 и формулу =A10 в ячейке B10.
Старый 11.06.2010, 11:30   #17  
Serg is offline
Serg
Участник
 
116 / 30 (2) +++
Регистрация: 12.02.2002
Проблема в том, что бы определить этот range, а он динамический т.е. на входе есть значения типа координат 1:1 до 100:100
Старый 11.06.2010, 12:13   #18  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Как-то так? Выделяется 10 первых строк:
X++:
{
    Form                form = new Form();
    Args                args = new Args();
    FormRun             formRun;
    FormActiveXControl  ss;

    COM                 worksheet;
    COM                 range;
    COM                 cells;
    ;

    form.addDesign('Design');
    args.object(form);

    formRun = classFactory.formRunClass(args);
    formRun.init();
    formRun.design().caption('Табличный процессор');

    ss = formRun.design().addControl(FormControlType::ActiveX, 'Spreadsheet');
    ss.className('{0002E541-0000-0000-C000-000000000046}');     // Microsoft Office Spreadsheet 10.0
    //ss.className('{0002E559-0000-0000-C000-000000000046}');   // Microsoft Office Spreadsheet 11.0

    ss.heightMode(FormHeight::ColumnHeight);
    ss.widthMode(FormWidth::ColumnWidth);

    range = ss.Range("A1");
    worksheet = range.Parent();
    cells = worksheet.Cells();
    range = ss.Range(cells.Item(1,1),cells.Item(10,10)); // ЭТО???
    range = range.EntireRow();
    box::info(range.Address(true,true,-4150)); // R1:R10
    range.Select();

    formRun.run();
    formRun.wait();
}
За это сообщение автора поблагодарили: Serg (1).
Старый 17.06.2010, 10:26   #19  
Serg is offline
Serg
Участник
 
116 / 30 (2) +++
Регистрация: 12.02.2002
ок, все помогло.
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
aEremenko: Как обнаружить какой пользователь загружает процессор AOS? Blog bot DAX Blogs 4 23.12.2008 12:06
Табличный Mapping - список используеиых таблиц db DAX: Программирование 6 30.06.2004 10:40

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

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 05:17.