|
30.01.2007, 20:59 | #1 |
Участник
|
Иван, так первая строка интерпретируется как заголовок столбцов.
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 | #2 |
Участник
|
Интересно
Согласно 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 | #3 |
NavAx
|
|
|
31.01.2007, 09:58 | #4 |
Участник
|
Мэй би. Но я пробовал и с FirstRowHasNames=0 - результат тот же.
__________________
Axapta v.3.0 sp5 kr2 |
|
31.01.2007, 11:57 | #5 |
Участник
|
Исследование расширенных параметров подключения
Вообще чудеса.
Провел исследование: 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 | #6 |
Участник
|
Цитата:
Сообщение от 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 | #7 |
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 | #8 |
Участник
|
Кто нибудь портировал этот класс на AX 2009?
|
|
15.12.2009, 14:35 | #9 |
Moderator
|
В этом классе, вроде, не должно быть ничего такого, что помешало бы ему портироваться. А Вы пробовали и не получилось или что?
|
|
15.12.2009, 15:31 | #10 |
Участник
|
при компиляции класса в 2009 появляется такое сообщение Best Practise: TwC: объявление об использовании API COM.Fields, поскольку он защищен с применением разграничения доступа кода.
|
|
20.05.2010, 11:19 | #11 |
Участник
|
Количество строк?
X++: int getRecordCount() { if(rstExcel && rstExcel.State() != #adStateClosed) return rstExcel.RecordCount(); return -1; } Непонятно почему метод их не считает...? |
|
20.05.2010, 13:35 | #12 |
Administrator
|
Цитата:
__________________
Возможно сделать все. Вопрос времени |
|
20.05.2010, 17:29 | #13 |
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 | #14 |
Участник
|
Пользуюсь классом ExcelImportADO в 2009 AX. Создаю общие журналы (через axLedgerJournalTrans)
Очень удобно, все хорошо. Только когда файл грузишь где строк тысяч 10, заметно что первые 1000 строк грузит гораздо быстрей чем следущие 1000 и так по нарастающей. Можно ли как то оптимизировать? может быть кэш очистить или еще что-то? На классе который грузит RunOn - Called from. |
|
20.05.2010, 12:37 | #15 |
Участник
|
Метод RecordCount() вроде бы возвращает осмысленное значение лишь для курсора типа static, в то время как в импорте по умолчанию используется курсор типа forward-only (он немного быстрее работает) - см. метод new() класса.
|
|
|
За это сообщение автора поблагодарили: propeller (1). |
21.06.2010, 17:31 | #16 |
Участник
|
Из того, что относится к собственно классу импорта, в голову приходит только тип курсора: у конструктора есть опциональный параметр int _cursorType = #adOpenForwardOnly, можно попробовать поставить #adOpenStatic (макрос из CCADO), тогда открываться файл будет чуть дольше, но скорость выборки строк должна стать одинаковой. Впрочем, я бы еще прошелся профилировщиком по коду импорта в целом - весьма вероятно, что замедление происходит где-то вне упомянутого класса. Причем оно может быть обусловлено совершенно безобидными на первый взгляд конструкциями, см., например, Channel9: Peter Villadsen and Gustavo Plancarte: X++ to MSIL:
Цитата:
Сообщение от belugin
Было одно место при разноске больших журналов, где существенную долю составляло простое присваивание типа a = b, где b - ссылка на объект с кучей связанных объектов. Именно из-за детерминированного сборщика мусора, который обязан собрать весь мусор прямо в момент его появления (кто-то блогпост еще писал по этому поводу).
|
|
24.08.2010, 10:58 | #17 |
Участник
|
Проблема: класс 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 |
|
22.02.2011, 11:33 | #18 |
Участник
|
Возникла такая проблема, при использовании данного класса:
X++: xlImport = new ExcelImportADO(filename); while(!xlImport.eof()) { strItemID = xlImport.getFieldValue(1); strItemAmount = xlImport.getFieldValue(3); ... Если кто-то сталкивался, подскажите как быть, плиз. |
|
02.03.2011, 09:10 | #19 |
Молодой, подающий надежды
|
Небольшой глюк
В методе getExcelSheetNames() помимо названий самих листов в контейнер попадают названия закладок (bookmark), что естественно приводит к ошибке, если закладка попадает в контейнер имен первой. Единственный способ отличить закладку от листа, который я пока нашел, это наличие символа '$' в названии листа. Вопрос: на сколько это корректно?
|
|
24.08.2010, 11:31 | #20 |
Administrator
|
Попробуйте "Excel 8.0" заменить на "Excel 12.0 Xml". Не уверен - т.к. нет возможности оперативно проверить
__________________
Возможно сделать все. Вопрос времени |
|