czwartek, 27 września 2012

Odczyt danych z pliku Excel

Oto moja autorska metoda odczytu danych z pliku excel, umożliwia ona :
  • odczyt z pliku xlsx bez konieczności posiadania zainstalowanego porgramu Microsoft Excel
  • jest nieporównywalnie szybsza i wygodniejsza od innych znanych mi metod (a prawdopodobnie znam je wszystkie)
  • obsługuje duże pliki xlsx (mechanizmy oparte na połączeniach COM mają z tym problem)

Potrzebna jest biblioteka EPPlus która w swojej standardowej postaci znajduje się pod adresem http://epplus.codeplex.com. Aby użyć tej biblioteki w połączeniu z Dynamics AX 2009 wymagała ona pewnych zmian (standardowa biblioteka używa pewnych składni języka C# z którą DAX sobie nie radzi).

Poprawiona przeze mnie wersja biblioteki znajduje się pod adresem AX_EPPlus.zip (kod źródłowy zostanie opublikowany niedługo).


Przykład użycia :
Bibliotekę dodajemy do referencji w Dynamics AX 2009 (po stronie klienta).

  
static void SBR_ReadFromExcelFile(Args _args)
{
    OfficeOpenXml.ExcelPackage      package;
    OfficeOpenXml.ExcelWorkbook     workBook;
    OfficeOpenXml.ExcelWorksheets   workSheets;
    OfficeOpenXml.ExcelWorksheet    workSheet;
    System.IO.FileInfo              file;
    CLRObject                       clrException;
    int                             i;
    CustAccount                     custAccount;
    Amount                          amount;
    ;
    try {
        file = new  System.IO.FileInfo("c:\\temp\\a.xlsx");
        package = new OfficeOpenXml.ExcelPackage(file);

        workBook    = package.get_Workbook();
        workSheets  = workBook.get_Worksheets();
        // read from first sheet
        workSheet   = workSheets.get_Item(1);

        i = 1;
        while(!CLRInterop::isNull(worksheet.AxGetValue(i,1)))
        {
            custAccount = worksheet.AxGetValue(i,1);

            // if cell is empty NULL value will be returned
            if (!CLRInterop::isNull(worksheet.AxGetValue(i,2)))
            {
                // read value from excel file
                amount = worksheet.AxGetValue(i,2);
            } else {
                // set default value for empty cell
                amount = 0;
            }

            print custAccount, '  ', amount;

            i++;
        }
        Box::info(strFmt('Done. %1 rows readed.');
    }
    catch( Exception::CLRError )
    {
        clrException    =   CLRInterop::getLastException();
        if( clrException )
        {
            info( CLRInterop::getAnyTypeForObject( clrException.get_Message() ) );
        }
    }
    catch( Exception::Internal )
    {
        clrException    =   CLRInterop::getLastException();
        if( clrException )
        {
            info( CLRInterop::getAnyTypeForObject( clrException.get_Message() ) );
        }
    }
}

czwartek, 20 września 2012

Księgowanie produkcji z kodu

  
static void SBR_FinishProduction(Args _args)
{
    ProdTable                   prodTable = ProdTable::find('PRD_00005079');
    ProdMultiReportFinished     prodMultiReportFinished;
    ProdParmReportFinished      prodParmReportFinished;
    ParmUpdate                  parmUpdate;
    ;
    ttsBegin;

    prodMultiReportFinished = ProdMultiReportFinished::construct(null);
    prodParmReportFinished  = prodMultiReportFinished.defaultParmBuffer();
    parmUpdate              = prodMultiReportFinished.defaultParmUpdate();

    RunBaseMultiParm::initParm(prodMultiReportFinished);
    prodMultiReportFinished.insertParmUpdate(parmUpdate);

    // dodajemy produkcję
    prodParmReportFinished.Linenum++;
    prodMultiReportFinished.insert(prodTable, prodParmReportFinished);

    // modyfikujemy ilość
    // prodParmReportFinished.QtyGood = 1;
    // prodParmReportFinished.update();

    prodTable.status().runReportFinished(prodParmReportFinished);

    ttsCommit;
    pause;
}

czwartek, 6 września 2012

Przechwytywanie wyjątków we własnym przebiegu.

Przechwytywanie wyjątków we własnym przebiegu.

Gdy wystąpi wyjątek w jakimś Jobie, zostanie on przedstawiony w następujący sposób.

Dużo wygodniejszą formą (dla mnie) jest przedstawienie do w takiej formie :
Wtedy okno infoLog można wykorzystać do czegoś innego.

Efekt taki osiągamy następującym kodem :
  
static void SBR_ExceptionDemo(Args _args)
{
    AifInfoLog                      aifInfoLog;
    SysInfoLogEnumerator            infoLogEnum;
    SysInfologMessageStruct         infoMessageStruct;
    ;
    try {
        aifInfoLog = new AifInfoLog();
        
        ttsBegin;

        // linia powodujaca wyjatek
        SalesTable::find('XXX').update();
        
        ttsCommit;

    } catch {
        infoLogEnum = SysInfoLogEnumerator::newData(aifInfoLog.getInfoLogData());
        infolog.clear(0);

        while(infoLogEnum.moveNext())
        {
            infoMessageStruct = SysInfologMessageStruct::construct(infoLogEnum.currentMessage());
            infolog.messageWin().addLine( 'ERROR : ' + infoMessageStruct.message() );
        }
    }
    
    pause;
}