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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 08.06.2006, 08:21   #1  
_and is offline
_and
Участник
 
1 / 10 (1) +
Регистрация: 08.06.2006
Построчный импорт из Excel через COM
Добрый день.

Импорт Excel при последовательном чтении из ячеек работает очень медленно (у меня ~500 ячеек в секунду, таблица из строк в 52 ячейки). Хотелось бы считывать данные построчно - скажем, считывать строку в массив и потом обрабатывать.
Такое возможно? (Есть пример построчной записи через метод value2 у range)
Старый 08.06.2006, 08:39   #2  
25-17 is offline
25-17
Участник
 
3 / 10 (1) +
Регистрация: 11.01.2006
А через XML не пробовал?? Excel файл это ведь по сути тот же xml файл
Старый 08.06.2006, 14:36   #3  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от _and
Импорт Excel при последовательном чтении из ячеек работает очень медленно (у меня ~500 ячеек в секунду, таблица из строк в 52 ячейки). Хотелось бы считывать данные построчно - скажем, считывать строку в массив и потом обрабатывать. Такое возможно?
Есть чудесный пример импорта данных через ADO. В частности, я таким образом переделывал импорт номенклатуры из Excel, в результате скорость возрасла чуть ли не на порядок. А если его еще обернуть в красивую формочку, то вообще красота получится. Я для импорта номенклатуры использовал такой вот заточенный под указанную формочку класс:
PHP код:
class Uni_ImportInventFromExcelADO
{
    
COM         cnnExcelrstExcelflds;                       // ADO: Connection, Recordset, Fields
    
LanguageId  languageId;
    
int         iMaxFieldsnStartRownCountLines;
    
str         strFileNamestrSheetName;
}
anytype adoFieldValue(int _iIdxboolean _asString true)
{
    
COM         fld;                                            // ADO: Field
    
;
    
fld flds.Item(_iIdx);
    return (
_asString this.adoStrValueFromExcel(fld.Value(), fld.Type(), true) : this.adoValueFromExcel(fld.Value(), fld.Type()));
}
str adoStrValueFromExcel(COMVariant _valint _typeboolean bDblRound false)
{
#CCADO
    
switch (_type)
    {
        case 
#adDouble:         return num2str(_val.double(),-1,(bDblRound ? 0 : -1),1,0);
        
case #adCurrency:       return num2str(_val.currency(),-1,-1,1,0);
        
case #adDate:           return date2str(_val.date(),123,2,2,2,2,4);
        
case #adBoolean:        return int2str(_val.boolean());
        
case #adVarWChar,
             #adLongVarWChar:   return _val.bStr();
    
}
    return 
'';
}
anytype adoValueFromExcel(COMVariant _valint _type)
{
#CCADO
    
switch (_type)
    {
        
// constants for types recognized by ADO for Excel
        
case #adDouble:         return _val.double();
        
case #adCurrency:       return _val.currency();
        
case #adDate:           return _val.date();
        
case #adBoolean:        return _val.boolean();
        
case #adVarWChar,
             #adLongVarWChar:   return _val.bStr();
    
}
    return 
'';
}
void finalize()
{
    
rstExcel.Close();
    
cnnExcel.Close();
}
// get Excel book active sheet name to use as a table name in select
protected str getExcelSheetName()
{
    
ComExcelDocument_RU Excel;
    
COM                 comDoccomAppSheet;

    if(
strSheetName)                                            // if we've been already called successfully...
        
return strSheetName;
    try
    {
        
Excel = new ComExcelDocument_RU();
        if(
Excel.open(strFileNamefalse))                      // Excel - don't show up
        
{
            
comDoc Excel.getComDocument();
            
comApp comDoc.Application();
            
Sheet  comApp.ActiveSheet();
            
strSheetName Sheet.name();
            
Excel.quitApplication(true);                        // true: Excel - don't ask to save the file
            
Excel.finalize();
        }
    }
    catch (
Exception::Error)
    {
        
Excel.quitApplication(true);
        
Excel.finalize();                                       // get lost anyway
    
}
    catch (
Exception::Internal)
    {
        
Excel.quitApplication(true);                            // emulate try/finally
        
Excel.finalize();
    }
    return 
strSheetName;
}
int getLinesReadCount()
{
    return 
nCountLines;
}
int getRecordCount()
{
#define.MaxRecordWeSupposeToRead(10000)
    
int i #MaxRecordWeSupposeToRead;
    
;
    if(
rstExcel && rstExcel.RecordCount()>=0)
        
rstExcel.RecordCount();
    return 
i;
}
void new(str _fileName int _nStartRow)
{
    
rstExcel    null;
    
cnnExcel    null;
    
nCountLines 0;
    
strSheetName'';
    
strFileName _fileName;
    
nStartRow   _nStartRow;
    
languageId  CompanyInfo::languageId();
}
boolean openFile()
{
#CCADO
// we need at least this number of columns
#define.ExcelIdxMax(8)
#localmacro.ADODBExcelConnectionString
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + %";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'"
#endmacro
    
boolean ok;
    ;
    
ok = (this.getExcelSheetName() != '');                      // first try to open file via COM
    
if(ok)
    {
        
cnnExcel    = new COM("ADODB.Connection");
        
cnnExcel.connectionString(#ADODBExcelConnectionString(strFileName));
        
cnnExcel.Open();
        
rstExcel    = new COM("ADODB.Recordset");               // #adOpenStatic to be able to read RecordCount
        
rstExcel.Open("SELECT * FROM [" strSheetName "$]"cnnExcel#adOpenForwardOnly);
        // check if we have enough fields to read
        
flds        rstExcel.Fields();
        
iMaxFields  flds.Count() - 1;
        if(
iMaxFields #ExcelIdxMax)
            
ok false;
    }
    return 
ok;
}
boolean importNext()
{
    
InventTable         inv;
    ;

    if(
rstExcel.EOF())                                      // no more data
        
return false;

    
// import using this.adoFieldValue()

    
rstExcel.MoveNext();
    
nCountLines++;
    return 
true;

Соотв., в формочке сначала идет вызов openFile(), для статистики берется общее количество строк getRecordCount() и вызывается importNext(), пока этот метод не вернет false. Градусник на форме можно обновлять по данным getLinesReadCount().
По поводу получения количества записей из ADODB.RecordSet. Для типа курсора adOpenForwardOnly rstExcel.RecordCount() всегда будет возвращать 0. Чтобы получать реальное число записей, надо открывать RecordSet с курсором adOpenStatic, но тогда на большом файле получатся ощутимые тормоза при открытии и лишний расход памяти.

Последний раз редактировалось gl00mie; 08.06.2006 в 14:41.
За это сообщение автора поблагодарили: Gustav (3).
Старый 05.07.2011, 14:05   #4  
nano3 is offline
nano3
Участник
 
57 / 24 (1) +++
Регистрация: 21.03.2007
gl00mie, посмотрел приложенный вами класс. Есть параметр _nStartRow, но далее он нигде не используется. Не подскажите куда его подсунуть?
X++:
void new(str _fileName , int _nStartRow) 
{ 
    rstExcel    = null; 
    cnnExcel    = null; 
    nCountLines = 0; 
    strSheetName= ''; 
    strFileName = _fileName; 
    nStartRow   = _nStartRow; 
    languageId  = CompanyInfo::languageId(); 
}
Вроде бы разобрался... Чтобы перейти на нужную запись надо использовать rstExcel.Move();

Последний раз редактировалось nano3; 05.07.2011 в 14:54.
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Импорт из 'офисной БД' (Excel, Access) Gustav DAX: База знаний и проекты 4 07.06.2008 17:17
Импорт строк PurchLine (через функционал) kaw DAX: Функционал 8 20.03.2008 14:49
Помогите сделать действие в Excel через COM kashperuk DAX: Программирование 25 10.09.2007 15:59
Импорт из Excel через шаблон стандартными средствами аксапты NV DAX: Функционал 5 20.01.2005 12:26
Импорт бюджета из Excel OliaM DAX: Функционал 16 13.01.2005 21:56

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

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

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