![]() |
#1 |
Участник
|
![]()
Доброго дня.
Сторонняя программа дает Excel-файл. Я его порезал убрав лишнее. Файл в аттаче. Суть в том, что есть данные в первом столбце и нет во втором. И вот такой код есть: X++: static void checkExcell(Args _args) { FilePath path=''; container conFilter = ["Файл (*.xls)", "*.xls"]; SysExcelApplication exappl; SysExcelCells excells; SysExcelWorksheets exsheets; SysExcelWorksheet exsheet; int row; real a,b; ; path = WinAPI::getOpenFileName(0,conFilter,"", "Укажите файл ",'',""); if (!path) return; exappl = SysExcelApplication::construct(); exappl.workbooks().open(path); exsheets = exappl.workbooks().item(1).worksheets(); exsheet = exsheets.itemFromNum(1); excells = exsheet.cells(); for(row = 1;row<3;row++) { a = excells.item(row,1).value().double(); //info(strfmt('%1',a)); // строка 1 b = excells.item(row,2).value().double(); info(strfmt('%1',a)); // строка 2 info(strfmt('%1',b)); } exappl.quit(); } Во втором случае выводится ожидаемое. В первом же случае, вместо 0 (в ячейке 2-го столбца пусто) получаем данные из первого столбца. Если в файле во второй колонке проставить значения, а потом удалить - все опять корректно работает. Axapta 2009. В 3-й такой проблемы не наблюдаю. |
|
|
За это сообщение автора поблагодарили: S.Kuskov (2). |
![]() |
#2 |
Участник
|
Интересно. Видимо второй (и последующие) вызов метода item() натыкается на какой-то мусор, оставшийся после первого вызова. А вызов info() каким-то образом подчищает этот мусор.
В качестве workaround могу предложить позиционироваться на ячейке при помощи метода offset: X++: static void checkExcell(Args _args) { FilePath path=''; container conFilter = ["Файл (*.xls)", "*.xls"]; SysExcelApplication exappl; SysExcelCells excells; SysExcelWorksheets exsheets; SysExcelWorksheet exsheet; SysExcelCell excell; // fix int row; real a,b; ; path = WinAPI::getOpenFileName(0,conFilter,"", "Укажите файл ",'',""); if (!path) return; exappl = SysExcelApplication::construct(); exappl.workbooks().open(path); exsheets = exappl.workbooks().item(1).worksheets(); exsheet = exsheets.itemFromNum(1); excells = exsheet.cells(); excell = excells.item(1,1); // fix for(row = 1;row<3;row++) { //a = excells.item(row,1).value().double(); a = excell.offset(row - 1, 0).value().double(); // fix //info(strfmt('%1',a)); // строка 1 //b = excells.item(row,2).value().double(); b = excell.offset(row - 1, 1).value().double(); // fix info(strfmt('%1',a)); // строка 2 info(strfmt('%1',b)); } exappl.quit(); } |
|
|
За это сообщение автора поблагодарили: Logger (3), Димитрий (1). |
![]() |
#3 |
Участник
|
Да, действительно. Так заработало корректно.
Но, код подобного типа расскидан по системе, т.к. даже не думал, что можно в такое вляпаться. Честно скажу, что в большей степени бы порадовала заплатка на класс работы с Экселем. ![]() |
|
![]() |
#4 |
Участник
|
Да, так и получилось. На SysExcelCells
X++: public SysExcelCell item(int _row, int _column, boolean first = false) { if (first) return SysExcelCell::construct(version,COM::createFromVariant(cells.item(_row,_column))); else { if (!excell) excell = this.item(1,1,true); return excell.offset(_row - 1, _column-1); } } SysExcelCell excell; Работает. |
|
![]() |
#5 |
Участник
|
Но проблем при такой заплатке есть.
Если первая ячейка объединена с рядом стоящими, то работает неверно. |
|
![]() |
#6 |
Участник
|
Общее правило при работе с любыми внешними (по отношению к Axapta) объектами:
Следует избегать многосоставных конструкций. Со многими точками. А в данном случае, нужно просто явно указать класс объекта, который будет выполнять обработку. В данном случае - чтение значение ячейки X++: static void checkExcell(Args _args) { FilePath path=''; container conFilter = ["Файл (*.xls)", "*.xls"]; SysExcelApplication exappl; SysExcelCells excells; SysExcelWorksheets exsheets; SysExcelWorksheet exsheet; int row; real a,b; // Добавчик SysExcelCell excellOne; SysExcelCell excellTwo; ; path = WinAPI::getOpenFileName(0,conFilter,"", "Укажите файл ",'',""); if (!path) return; exappl = SysExcelApplication::construct(); exappl.workbooks().open(path); exsheets = exappl.workbooks().item(1).worksheets(); exsheet = exsheets.itemFromNum(1); excells = exsheet.cells(); for(row = 1;row<3;row++) { // Вот это надо сделать excellOne = excells.item(row,1); excellTwo = excells.item(row,2); a = excellOne.value().double(); //info(strfmt('%1',a)); // строка 1 b = excellTwo.value().double(); info(strfmt('%1',a)); // строка 2 info(strfmt('%1',b)); } exappl.quit(); }
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
![]() |
#7 |
Участник
|
Цитата:
Сообщение от Владимир Максимов
![]() Общее правило при работе с любыми внешними (по отношению к Axapta) объектами:
Следует избегать многосоставных конструкций. Со многими точками. А в данном случае, нужно просто явно указать класс объекта, который будет выполнять обработку. В данном случае - чтение значение ячейки |
|
![]() |
#8 |
Участник
|
Думаю, что "обертка" не особо помогает при не явной инициализации промежуточных COM-объектов. Все "скрытые" COM-объекты - потенциальный источник проблем. Кто его знает как там с распределением памяти дела обстоят? Лучше уж потратить лишние переменные и иницилизировать все промежуточные COM-объекты явным образом.
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
Теги |
excel |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|