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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 24.01.2007, 21:51   #1  
DTD is offline
DTD
Участник
 
183 / 18 (1) ++
Регистрация: 09.08.2005
Экспорт из Excel, глобальные переменные
Как известно при импорте из excel есть возможность подставлять свой код для конвертации и проверки строк.

Изврашенцы-консультанты придумали что id должно вытаскиватся из определенной number sequence и подставлятся в каждую импортируемую строку. Но .. не уникальные, а один id для всего фаила (при вставкe в эту таблицу через форму id подставляются как обычно, с инкриментом, та же number seq).

Вроде бы с первого взгляда все просто, но на практике непонятно где сохранять это значение, т.к. ClassDeclaration и т.д. не доступно ..

Мысль с таблицей вроде тоже отпала, так как непонятно к чeму привязывать выташенный номер, в методах доступны только поля записи импортируемой таблицы ...

Можeт у кого есть идеи ..

Код который требуется:

X++:
PriceDiscTable convert(PriceDiscTable priceDiscTable, container inData)
{
    priceDiscTable.checkDate();

    --------------------------
    priceDiscTable.NEW_PriceDiscId = PriceDiscId_for_entire_file;
   --------------------------

    

    --------------------------
    priceDiscTable.NEW_PriceDiscId = NumberSeq::newGetNum( 
    NumberSeqReference::findReference(typeId2ExtendedTypeId(typeid(NEW_PriceDiscId))),true ).num();
    --------------------------

    return priceDiscTable;
}
__________________
_databaseTransDelete ... bl@$ !

Последний раз редактировалось DTD; 24.01.2007 в 21:53.
Старый 24.01.2007, 22:54   #2  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Может воспользоваться infolog.GlobalCache() ?
X++:
PriceDiscTable convert(PriceDiscTable priceDiscTable, container inData)
{
    SysGlobalCache globalCache = infolog.GlobalCache();
    NEW_PriceDiscId NEW_PriceDiscId = globalCache.get("Import", "PriceDiscId");
    ;
    priceDiscTable.checkDate();
    if (!NEW_PriceDiscId)
    {
        NEW_PriceDiscId = NumberSeq::newGetNum( NumberSeqReference::findReference( typeId2ExtendedTypeId( typeid( NEW_PriceDiscId ) ) ),true ).num();
        globalCache.set("Import", "PriceDiscId", NEW_PriceDiscId);
    }    
    priceDiscTable.NEW_PriceDiscId = NEW_PriceDiscId;
    return priceDiscTable;
}
__________________
Axapta v.3.0 sp5 kr2
За это сообщение автора поблагодарили: belugin (11), DTD (1).
Старый 25.01.2007, 12:53   #3  
DTD is offline
DTD
Участник
 
183 / 18 (1) ++
Регистрация: 09.08.2005
Цитата:
Сообщение от AndyD Посмотреть сообщение
Может воспользоваться infolog.GlobalCache() ?
При каждом заходе в функцию перем. PriceDiscId пустая.

Я поставил два инфолога, один перед if, второй после, результат:
пусто
NS0010
пусто
NS0011

Вообще странно, у етих переменных видимость же должна быть в пределах сессии ..

И если бы работало, надо бы было как то обнулять эту переменную после каждого фаила, но думаю это бы решилось модификацией самого класса который реализует импорт
__________________
_databaseTransDelete ... bl@$ !
Старый 25.01.2007, 16:01   #4  
DTD is offline
DTD
Участник
 
183 / 18 (1) ++
Регистрация: 09.08.2005
В обшем решил путем добавления скрытого поля в InventParameters и инициализации / сбрасыванием его перед/после импортом таблицы в SysDataImportExcel/importTable.
__________________
_databaseTransDelete ... bl@$ !
Старый 25.01.2007, 16:09   #5  
oip is offline
oip
Axapta
Лучший по профессии 2014
 
2,564 / 1416 (53) ++++++++
Регистрация: 28.11.2005
Записей в блоге: 1
А если несколько пользователей одновременно импорт запустят?
Старый 25.01.2007, 19:15   #6  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
А как чисто технически можно закрыть для редактирования один из методов класса? Или наоборот, открыть только один?
Старый 25.01.2007, 20:04   #7  
DTD is offline
DTD
Участник
 
183 / 18 (1) ++
Регистрация: 09.08.2005
Цитата:
Сообщение от oip Посмотреть сообщение
А если несколько пользователей одновременно импорт запустят?
Значит будет только один запускать. Буду рад если вы подскажeте более оптимальное решение.
__________________
_databaseTransDelete ... bl@$ !
Старый 25.01.2007, 20:09   #8  
DTD is offline
DTD
Участник
 
183 / 18 (1) ++
Регистрация: 09.08.2005
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
А как чисто технически можно закрыть для редактирования один из методов класса? Или наоборот, открыть только один?
Там вообще не класс, код компилируется из текста на ходу, вот как ето выглядит в дебаггере:

X++:
[c]    \Data Dictionary\Tables\PriceDiscTable\Methods\checkDate                               7
[c]    <runtime compiled code>\boolean import(PriceDiscTable priceDiscTable, container inData)                  
[s]    {                                                                                                        
[s]    ;                                                                                                        
[s]    priceDiscTable.checkDate();                                                                
[s]        return true;                                                                                         
[s]    }                                                                                                        
[c]    \Classes\SysDataImportDefBase\canImportRecord                                                          18
[c]    \Classes\SysDataImportDefBase\importTable                                                              87
[c]    \Classes\sysdataimportexcel\importTable                                                                 8
[c]    \Classes\SysDataImportDefBase\import                                                                   36
[c]    \Classes\sysdataimportexcel\import                                                                     10
[c]    \Classes\SysDataImportDefBase\run                                                                       5
[s]    \Classes\SysDataImport\main                                                                            10
[s]    \Classes\MenuFunction\runServer                                                                          
[c]    \Classes\FormFunctionButtonControl\Clicked
__________________
_databaseTransDelete ... bl@$ !
Старый 25.01.2007, 21:17   #9  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Так речь идет о четверке?

В 3.0 приведенный мной код отлично работает.
__________________
Axapta v.3.0 sp5 kr2

Последний раз редактировалось AndyD; 25.01.2007 в 21:31.
Старый 26.01.2007, 10:38   #10  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Без сохранения кода ВНЕ текущего метода задача не имеет решения. Не важно в чем ты там будешь сохранять значение: в глобальной переменной, поле таблицы или еще как.

Примерная логика твоего кода должна быть такой:

if (НЕ существует номер) присвоить номер;

Проблема заключается в том, что внутри метода ты никак, никоим образом, не сможешь узнать КОГДА был создан этот номер. В каком процессе. Не физическом, а логическом.

Он был создан вот сейчас, при запуске вот этого метода, или РАНЬШЕ, при предыдущем запуске? При импорте, произведенном этим же пользователем, но пятью минутами раньше.

Другими словами, твой табличный метод импортирует ОДНУ строку. Он ничего не знает о том, успешно или не успешно импортировались ДРУГИЕ строки. Т.е. остался ли номер от импорта предыдущей строки данного процесса или же от импорта другой таблицы.

Если речь идет о табличном методе, то в данный метод значение номера должно передаваться как параметр и никак иначе. НЕЛЬЗЯ формировать номер ВНУТРИ табличного метода. В противном случае, задача не имеет решения.
Старый 26.01.2007, 11:27   #11  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Проблема заключается в том, что внутри метода ты никак, никоим образом, не сможешь узнать КОГДА был создан этот номер. В каком процессе. Не физическом, а логическом.
я бы сказал, что это очень сильное утверждение. Возможно, это сложно сделать, но наверное как-то извратиться можно.

например использовать вот это: AxPath://AOT/System%20Documentation/Classes/xApplication/curTransactionId
Старый 26.01.2007, 12:21   #12  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от belugin Посмотреть сообщение
я бы сказал, что это очень сильное утверждение. Возможно, это сложно сделать, но наверное как-то извратиться можно.

например использовать вот это: AxPath://AOT/System%20Documentation/Classes/xApplication/curTransactionId
Из описания не ясно, что собственно возвращает curTransactionId (у меня AXAPTA 2.5), но, судя по названию, это некий идентификатор транзакции? Т.е. нечто, настроенное ВНЕ процедуры. Причем Вы исходите из предположения, что сама транзакция имеет место быть. На каком основании?

Предположим, Вы обрабатываете последовательно 2 записи. Вы можете, находясь внутри процедуры обработки ОДНОЙ записи ответить на вопрос:

Сколько записей всего было обработано по этому же самому документу Excel?

Вы вообще обрабатываете НОВЫЙ документе Excel (первая строка этого документа) или же очередную строку того же самого документа Excel?

Каким образом знание идентификатора транзакции поможет ответить на этот вопрос?

Главная проблема данной задачи - это узнать первую или НЕ первую запись файла Excel сейчас обрабатываем. Дальше все просто. Но КАК находясь внутри процедуры обработки ОДНОЙ записи это узнать? Никак! Нужен внешний счетчик уже обработанных записей.
Старый 26.01.2007, 12:33   #13  
DTD is offline
DTD
Участник
 
183 / 18 (1) ++
Регистрация: 09.08.2005
Цитата:
Сообщение от AndyD Посмотреть сообщение
Так речь идет о четверке?

В 3.0 приведенный мной код отлично работает.
Да, забыл указать, DAX4.1
__________________
_databaseTransDelete ... bl@$ !
Старый 26.01.2007, 12:44   #14  
DTD is offline
DTD
Участник
 
183 / 18 (1) ++
Регистрация: 09.08.2005
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Главная проблема данной задачи - это узнать первую или НЕ первую запись файла Excel сейчас обрабатываем. Дальше все просто. Но КАК находясь внутри процедуры обработки ОДНОЙ записи это узнать? Никак! Нужен внешний счетчик уже обработанных записей.
Так это жe и есть оригинальный вопрос ...

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

У меня есть еще несколько идей как это преодолеть, просто больше програмирования, можeт как нибудь потом попробую:

1. Сделать отдельную таблицу с полями: требуемый ID и какой нибудь уникальный идентификатор сессии. Просто писать только одно значнеие на сессию.

2. Этот код хранится в таблице в виде текста, возможно можно модифицировать его, меняя константу там перед вызовом цикла обработчика записай. . Таблица выглядит так как будто запись создается для каждого запуска импорта, т.е. конфликтов не должно быть.
__________________
_databaseTransDelete ... bl@$ !
Старый 26.01.2007, 13:04   #15  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от DTD Посмотреть сообщение
1. Сделать отдельную таблицу с полями: требуемый ID и какой нибудь уникальный идентификатор сессии. Просто писать только одно значнеие на сессию.
Вы запустили процедуру импорта первый раз - все замечательно.

Затем, не выходя из AXAPTA, находясь в той же сессии, запустили процедуру импорта еще раз.

И вот тут-то и проблема. Все идентификаторы те же самые, но импорт ДРУГОЙ. Нужен НОВЫЙ код. А Вы возьмете старое значение из того, что было сохранено.

Цитата:
Сообщение от DTD Посмотреть сообщение
2. Этот код хранится в таблице в виде текста, возможно можно модифицировать его, меняя константу там перед вызовом цикла обработчика записай. . Таблица выглядит так как будто запись создается для каждого запуска импорта, т.е. конфликтов не должно быть.
Т.е. каждая запись будет иметь свой идентификатор? Генерация кода происходит для каждой записи в отдельности или для всей процедуры импорта (всех записей) одного файла Excel?
Старый 26.01.2007, 13:35   #16  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Главная проблема данной задачи - это узнать первую или НЕ первую запись файла Excel сейчас обрабатываем. Дальше все просто. Но КАК находясь внутри процедуры обработки ОДНОЙ записи это узнать? Никак! Нужен внешний счетчик уже обработанных записей.
Насколько я знаю ( AxPath://AOT/Classes/SysDataImport/importData?line=113&pos=13 ) импорт осуществляется в одной транзации. Таким образом зная ее идентификатор, можно запомнить его в глобальном кеше для клиента и а потом проверять не отличается ли он от предыдущего.

Это не точно. Надо проверить.
Старый 26.01.2007, 13:48   #17  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Вы запустили процедуру импорта первый раз - все замечательно.

Затем, не выходя из AXAPTA, находясь в той же сессии, запустили процедуру импорта еще раз.

И вот тут-то и проблема. Все идентификаторы те же самые, но импорт ДРУГОЙ. Нужен НОВЫЙ код. А Вы возьмете старое значение из того, что было сохранено.
По моему, здесь остается единственный вопрос - сброс сохраненного значения перед началом импорта (или после окончания).

В общем-то, для этого можно воспользоваться тем же классом Info - добавить в обработчик таймера (addTimeOut) свой класс, в котором сбрасывать сохраненный параметр. Параметр idle = true. Время срабатывания - минимальное.

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

В результате, как только импорт отработает, запустится метод по таймеру и сбросит сохраненный параметр.
__________________
Axapta v.3.0 sp5 kr2
Старый 26.01.2007, 15:27   #18  
DTD is offline
DTD
Участник
 
183 / 18 (1) ++
Регистрация: 09.08.2005
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Вы запустили процедуру импорта первый раз - все замечательно.

Затем, не выходя из AXAPTA, находясь в той же сессии, запустили процедуру импорта еще раз.

И вот тут-то и проблема. Все идентификаторы те же самые, но импорт ДРУГОЙ. Нужен НОВЫЙ код. А Вы возьмете старое значение из того, что было сохранено.
Это было понятно с самого начала и решено путем сбрасывания значения после каждого импорта, посмотрите пост #4 -" ...и инициализации / сбрасыванием его перед/после импортом таблицы в SysDataImportExcel/importTable"
__________________
_databaseTransDelete ... bl@$ !
Старый 26.01.2007, 15:31   #19  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,691 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от DTD Посмотреть сообщение
Это было понятно с самого начала и решено путем сбрасывания значения после каждого импорта, посмотрите пост #4 -" ...и инициализации / сбрасыванием его перед/после импортом таблицы в SysDataImportExcel/importTable"
У Вас произошла ошибка в процессе импорта. Флаг установился, но не сбросился. Ваши действия?

==============
Минуточку!

SysDataImportExcel/importTable относится к импорту ВСЕЙ таблицы? Не одной строки, а именно ВСЕХ строк? Если вот в этом методе и формировать твое значение NEW_PriceDiscId и записывать в спец.поле таблицы или переменную класса Global, а в методе разбора одной строки просто считывать это значение?

Последний раз редактировалось Владимир Максимов; 26.01.2007 в 15:40. Причина: Сразу не понял
Старый 26.01.2007, 18:50   #20  
DTD is offline
DTD
Участник
 
183 / 18 (1) ++
Регистрация: 09.08.2005
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
SysDataImportExcel/importTable относится к импорту ВСЕЙ таблицы? Не одной строки, а именно ВСЕХ строк? Если вот в этом методе и формировать твое значение NEW_PriceDiscId и записывать в спец.поле таблицы или переменную класса Global, а в методе разбора одной строки просто считывать это значение?


Гениально !
__________________
_databaseTransDelete ... bl@$ !
Теги
импорт, импорт из excel, критерии

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Экспорт стандартных отчетов в Excel ? ena_ax DAX: Программирование 14 12.04.2010 14:16
Экспорт в Excel exodus DAX: Программирование 1 23.01.2008 09:35
Экспорт из Excel... soin DAX: Администрирование 10 24.01.2007 21:32
Экспорт в Excel. Проблема с '\n' axaLearner DAX: Программирование 12 17.04.2006 18:43
Экспорт в Excel через WorkBooks.OpenText() Владимир Максимов DAX: Программирование 2 09.04.2004 17:16

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

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

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