21.01.2007, 21:45 | #21 |
Участник
|
На днях обнаружил интересную особенность в именовании листов Excel и том, в каком порядке возвращаются данные о листах (таблицах ADOX.Catalog). Во-первых, если в названиях листов есть какие-то неположеные символы, названия берутся в одинарные кавычки, причем просто лист обзывается 'Sheet 1', а вот именованный диапазон автофильтра возвращается как 'Sheet 1$'Smth, т.е. во втором случае кавычки идут после '$'. В связи с этим кроме символа $ и всего, что идет после него, из имени теперь вырезаются и одинарные кавычки. Во-вторых, как выяснилось, данные о листах (таблицах ADOX.Catalog) возвращаются отсортированные без учета регистра по названиям листов, а вовсе не в том порядке, в каком листы представлены в книге Excel. Поскольку класс по умолчанию использует в выборке имя листа, первого с точки зрения ADOX.Catalog, это может иметь нежиданный эффект - обратите внимание...
Обновленная версия класса, вырезающая кавычки из имен листов, выложена в первом сообщении темы. |
|
|
За это сообщение автора поблагодарили: blokva (2). |
22.01.2007, 09:06 | #22 |
Пенсионер
|
Да есть такая штука, прошу меня простить, я это тоже обнаружил, исправил у себя, а обществу не сообщил...забыл в запарке
__________________
Законы природы еще никто не отменял! А еще у меня растет 2 внучки!!! Кому интересно подробности тут: http://www.baby-shine.com/ |
|
30.01.2007, 19:53 | #23 |
Участник
|
Ошибка при импорте из прикрепленного файла
Посмотрите файл.
Запускаю импорт из него. Вместо первой сразу начинает импорт со второй строки. Какие варианты исправления и объяснения происходящего? Помимо этого, иногда неверно определяется число столбцов Excel. (больше 100 пишет) Код job для импорта, который использую: X++: static void WrongADOFileImport(Args _args) { ComExcelImportADO_UAI excel; Counter fieldCount; Counter curField; FileNameOpen fileName; ; filename = WinAPI::getOpenFileName(infolog.hWnd(), ["Microsoft Excel","*.xls"], '', "Выберите файл"); if (!filename) throw error("@SYS26757"); excel = new ComExcelImportADO_UAI(fileName); if (excel.openFile()) { fieldCount = excel.getFieldsCount(); box::info(int2str(fieldCount)); while (!excel.eof()) { info(excel.getFieldValue(1, true)); info(excel.getFieldValue(2, true)); info(excel.getFieldValue(3, true)); info(excel.getFieldValue(4, true)); info(excel.getFieldValue(5, true)); for (curField = 6; curField < fieldCount; curField++) { info(excel.getFieldValue(curField, true)); } return; //только первую строку //excel.moveNext(); } } } |
|
30.01.2007, 20:59 | #24 |
Участник
|
Иван, так первая строка интерпретируется как заголовок столбцов.
X++: static void CorrectADOFileImport(Args _args) { ExcelImportADO excel; Counter fieldCount; Counter curField; FileNameOpen fileName; COM adoxCatalog = new COM(@"ADOX.Catalog"); COM Tables; COM Table; COM Columns; COM Column; int i; ; filename = WinAPI::getOpenFileName(infolog.hWnd(), ["Microsoft Excel","*.xls"], '', "Выберите файл"); if (!filename) throw error("@SYS26757"); excel = new ExcelImportADO(fileName); if (excel.openFile()) { fieldCount = excel.getFieldsCount(); adoxCatalog.ActiveConnection(excel.getConnection()); Tables = adoxCatalog.Tables(); Table = Tables.Item(0); if (Table) { Columns = Table.Columns(); for (i=0;i<Columns.Count();i++) { Column = Columns.Item(i); if (Column) info(Column.Name()); } box::info(int2str(fieldCount)); while (!excel.eof()) { info(excel.getFieldValue(1, true)); info(excel.getFieldValue(2, true)); info(excel.getFieldValue(3, true)); info(excel.getFieldValue(4, true)); info(excel.getFieldValue(5, true)); for (curField = 6; curField < fieldCount; curField++) { info(excel.getFieldValue(curField, true)); } return; //только первую строку //excel.moveNext(); } } } }
__________________
Axapta v.3.0 sp5 kr2 |
|
31.01.2007, 00:38 | #25 |
Участник
|
Интересно
Согласно BUG: Excel ODBC Driver Disregards the FirstRowHasNames or Header Setting для Microsoft Jet OLE DB Provider должна работать возможность отключения с помощью параметра HDR=No этой возможности. Но у меня с такой строкой подключения "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + %1 + ";Extended Properties='Excel 8.0;Ndr=No;IMEX=1'" все равно первая строка принимается как заголовок (MDAC 2.7, ExcelXP) Код, который я привел выше, не совсем корректно отображает данные в таких ячейках. Во-первых, сортировка идет в алфавитном порядке. Во-вторых, для ячеек, содержащих цифровые данные, имена будут отображаться в видет F1, F2 и т.д. В третьих, если встретятся одинаковые наименования (например, "дата"), то имена будет идти как "дата", "дата1" и т.д. Сортировку можно побороть с помощью такого метода X++: { ExcelImportADO excel; Counter fieldCount; Counter curField; FileNameOpen fileName; COM Conn; COM SchemaTables; COM TableFields; COM SchemaColumns; COM Fields; COM Item; int i; ComVariant var; Array arr = new Array(Types::Class); Array values; str name; #define.adSchemaColumns(4) #define.adSchemaTables(20) ; filename = WinAPI::getOpenFileName(infolog.hWnd(), ["Microsoft Excel","*.xls"], '', "Выберите файл"); if (!filename) throw error("@SYS26757"); excel = new ExcelImportADO(fileName); if (excel.openFile()) { fieldCount = excel.getFieldsCount(); Conn = excel.getConnection(); SchemaTables = Conn.OpenSchema(#adSchemaTables); while (!SchemaTables.EOF()) { TableFields = SchemaTables.Fields(); Item = TableFields.Item("TABLE_NAME"); var = Item.value(); info(strfmt("Table name : '%1'", var.bStr())); arr.value(1, new ComVariant()); arr.value(2, new ComVariant()); arr.value(3, var); arr.value(4, new ComVariant()); SchemaColumns = Conn.OpenSchema(#adSchemaColumns, ComVariant::createFromArray(arr)); // к сожалению, сортировка для Excel не работает // SchemaColumns.sort("ORDINAL_POSITION"); values = new Array(Types::String); while (!SchemaColumns.Eof()) { Fields = SchemaColumns.Fields(); Item = Fields.Item("COLUMN_NAME"); var = Item.value(); name = var.bStr(); Item = Fields.Item("ORDINAL_POSITION"); var = Item.value(); values.value(var.double(), name); SchemaColumns.MoveNext(); } for (i=1;i<=values.lastIndex();i++) info(values.value(i)); break; //SchemaTables.MoveNext(); } } } Общая рекомендация - всегда оставлять первую строку для заголовка (в принципе, наименования столбцов можно не задавать. В этом случае будут использоваться мена F1, F2 и т.д.)
__________________
Axapta v.3.0 sp5 kr2 |
|
31.01.2007, 09:09 | #26 |
NavAx
|
|
|
31.01.2007, 09:58 | #27 |
Участник
|
Мэй би. Но я пробовал и с FirstRowHasNames=0 - результат тот же.
__________________
Axapta v.3.0 sp5 kr2 |
|
31.01.2007, 11:57 | #28 |
Участник
|
Исследование расширенных параметров подключения
Вообще чудеса.
Провел исследование: 1. Установил HDR=No в строке подключения, в результате получил такую строку: "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + %1 + ";Extended Properties='Excel 8.0;HDR=No;IMEX=1'" При этом первая строка не прочиталась. (То есть неверно сработало) 2. Установил HDR=No и FirstRowHasNames=0 в строке подключения, в результате получил такую строку: "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + %1 + ";Extended Properties='Excel 8.0;HDR=No;FirstRowHasNames=0;IMEX=1'" При этом первая строка прочиталась. (То есть верно сработало) 3. Убрал HDR=No из предыдущего варианта, в результате получил такую строку: "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + %1 + ";Extended Properties='Excel 8.0;FirstRowHasNames=0;IMEX=1'" При этом первая строка не прочиталась. (То есть неверно сработало) 4. Вернул на место. Получил строку, как в варианте 2. НО, при этом первая строка не прочиталась. (То есть неверно сработало) Тут я уже начал задумываться, а не случайным ли образом выдается этот параметр 5. Убрал FirstRowHasNames=0 и вернул HDR=Yes, в результате получил строку: "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + %1 + ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'" А теперь внимание!: Первая строка НЕ прочиталась (То есть верно сработало, точнее, сработало то неверно, но с требуемым результатом) Попробовав еще несколько различных комбинаций установил, что он этих двух параметров результат ЗАВИСИТ, но как именно - не установлено. Исследуемая система: MS Windows XP Pro MS Office Excel 2003 MDAC 2.81 |
|
31.01.2007, 15:25 | #29 |
Участник
|
Цитата:
Сообщение от kashperuk
Провел исследование:
1. Установил HDR=No в строке подключения, в результате получил такую строку: "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + %1 + ";Extended Properties='Excel 8.0;HDR=No;IMEX=1'" При этом первая строка не прочиталась. (То есть неверно сработало) 2. Установил HDR=No и FirstRowHasNames=0 в строке подключения, в результате получил такую строку: "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + %1 + ";Extended Properties='Excel 8.0;HDR=No;FirstRowHasNames=0;IMEX=1'" При этом первая строка прочиталась. (То есть верно сработало) 3. Убрал HDR=No из предыдущего варианта, в результате получил такую строку: "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + %1 + ";Extended Properties='Excel 8.0;FirstRowHasNames=0;IMEX=1'" При этом первая строка не прочиталась. (То есть неверно сработало) 4. Вернул на место. Получил строку, как в варианте 2. НО, при этом первая строка не прочиталась. (То есть неверно сработало) Тут я уже начал задумываться, а не случайным ли образом выдается этот параметр 5. Убрал FirstRowHasNames=0 и вернул HDR=Yes, в результате получил строку: "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + %1 + ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'" А теперь внимание!: Первая строка НЕ прочиталась (То есть верно сработало, точнее, сработало то неверно, но с требуемым результатом)
1) По умолчанию используется значение HDR=Yes; 2) Значение FirstRowHasNames вообще ни на что не влияет. Исследуемая система: MS Windows Server 2003 SP1 MS Office Excel 2003 SP2 Rus MDAC 2.81 (вроде он штатно идет с w2k3, по крайней мере, файлы odbc*.dll версии 3.526.1830.0) Цитата:
Попробовав еще несколько различных комбинаций установил, что он этих двух параметров результат ЗАВИСИТ, но как именно - не установлено.
PS. В ходе раскопок обнаружилось, по какому числу строк определяются типы колонок: HKLM\Software\Microsoft\Jet\4.0\Engines\Excel\TypeGuessRows, по умолчанию стоит восемь, как и написано в документации (раздел «A Caution about Mixed Data Types»). Впрочем, там же упоминается параметр MaxScanRows, которым это можно контролировать: установить значения от 1 до 16, либо поставить 0 для сканирования всех строк. Последний раз редактировалось gl00mie; 31.01.2007 в 16:01. |
|
|
За это сообщение автора поблагодарили: Logger (3). |
31.01.2007, 16:08 | #30 |
Moderator
|
Цитата:
Сообщение от gl00mie
PS. В ходе раскопок обнаружилось, по какому числу строк определяются типы колонок:
HKLM\Software\Microsoft\Jet\4.0\Engines\Excel\TypeGuessRows, по умолчанию стоит восемь, как и написано в документации (раздел «A Caution about Mixed Data Types»). Впрочем, там же упоминается параметр MaxScanRows, которым это можно контролировать: установить значения от 1 до 16, либо поставить 0 для сканирования всех строк. MaxScanRows не работает |
|
14.12.2009, 19:16 | #31 |
Участник
|
Кто нибудь портировал этот класс на AX 2009?
|
|
15.12.2009, 14:35 | #32 |
Moderator
|
В этом классе, вроде, не должно быть ничего такого, что помешало бы ему портироваться. А Вы пробовали и не получилось или что?
|
|
15.12.2009, 15:31 | #33 |
Участник
|
при компиляции класса в 2009 появляется такое сообщение Best Practise: TwC: объявление об использовании API COM.Fields, поскольку он защищен с применением разграничения доступа кода.
|
|
20.05.2010, 11:19 | #34 |
Участник
|
Количество строк?
X++: int getRecordCount() { if(rstExcel && rstExcel.State() != #adStateClosed) return rstExcel.RecordCount(); return -1; } Непонятно почему метод их не считает...? |
|
20.05.2010, 12:37 | #35 |
Участник
|
Метод RecordCount() вроде бы возвращает осмысленное значение лишь для курсора типа static, в то время как в импорте по умолчанию используется курсор типа forward-only (он немного быстрее работает) - см. метод new() класса.
|
|
|
За это сообщение автора поблагодарили: propeller (1). |
20.05.2010, 13:35 | #36 |
Administrator
|
Цитата:
__________________
Возможно сделать все. Вопрос времени |
|
20.05.2010, 17:29 | #37 |
Moderator
|
А что если радикально поменять метод на примерно такой:
X++: public int getRecordCount() { COM rstCount; COM fldCount; COMVariant fldValue; ; rstCount = new COM(@"ADODB.Recordset"); rstCount.Open(@"SELECT Count(*) FROM [" + strSheetName + @"$]", this.getConnection()); fldCount = rstCount.Fields(); fldCount = fldCount.Item(0); fldValue = fldCount.Value(); return fldValue.int(); } |
|
21.06.2010, 16:48 | #38 |
Участник
|
Пользуюсь классом ExcelImportADO в 2009 AX. Создаю общие журналы (через axLedgerJournalTrans)
Очень удобно, все хорошо. Только когда файл грузишь где строк тысяч 10, заметно что первые 1000 строк грузит гораздо быстрей чем следущие 1000 и так по нарастающей. Можно ли как то оптимизировать? может быть кэш очистить или еще что-то? На классе который грузит RunOn - Called from. |
|
21.06.2010, 17:31 | #39 |
Участник
|
Из того, что относится к собственно классу импорта, в голову приходит только тип курсора: у конструктора есть опциональный параметр int _cursorType = #adOpenForwardOnly, можно попробовать поставить #adOpenStatic (макрос из CCADO), тогда открываться файл будет чуть дольше, но скорость выборки строк должна стать одинаковой. Впрочем, я бы еще прошелся профилировщиком по коду импорта в целом - весьма вероятно, что замедление происходит где-то вне упомянутого класса. Причем оно может быть обусловлено совершенно безобидными на первый взгляд конструкциями, см., например, Channel9: Peter Villadsen and Gustavo Plancarte: X++ to MSIL:
Цитата:
Сообщение от belugin
Было одно место при разноске больших журналов, где существенную долю составляло простое присваивание типа a = b, где b - ссылка на объект с кучей связанных объектов. Именно из-за детерминированного сборщика мусора, который обязан собрать весь мусор прямо в момент его появления (кто-то блогпост еще писал по этому поводу).
|
|
24.08.2010, 10:58 | #40 |
Участник
|
Проблема: класс ExcelImportADO при открытии файла Excel 2007 дает ошибку. Работаю в AX 4.0 SP2 под Windows 7. При открытии того же файла, сохраненного в формате Excel 1997-2003 ошибки нет, все прекрасно читается.
Цитата:
Метод "Open" в COM-объекте класса "ADODB.Connection" возвратил код ошибки 0x80004005 (E_FAIL), который означает: Внешняя таблица не имеет предполагаемый формат.
Набор таблиц недоступен. Приложение Excel инициализировано? Метод "Open" в COM-объекте класса "ADODB.Connection" возвратил код ошибки 0x80004005 (E_FAIL), который означает: Внешняя таблица не имеет предполагаемый формат. Невозможно открыть файл «c:\2007.xlsx» Цитата:
#localmacro.ADODBExcelConnString
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + %1 + ";Extended Properties='Excel 8.0;HDR=No;FirstRowHasNames=0;IMEX=1'" #endmacro |
|