Создание и заполнение DBF файла в Microsoft Dynamics AX

В MS Dynamics AX приходится экспортировать данные для дальнейшей их обработки. В основном используют для этого Excel, так же используют другие форматы: текстовый, dbf таблицы и т.д. В этой статье я рассмотрю формат dbf таблиц, поскольку считаю, что данный материал будет полезен и не раз пригодится на различных проектах.

Итак, нужно создать класс, с помощью которого можно создать и заполнить dbf таблицу. Класс назовем DBFFiles, в нем буду использовать .NET объекты System.Data.OleDb.OleDbConnection для подключения к источнику данных, в нашем случае это dbf таблица и System.Data.OleDb.OleDbCommand для выполнения SQL инструкций с источником данных.

public class DBFFiles
{
    System.Data.OleDb.OleDbConnection connection;
    System.Data.OleDb.OleDbCommand command;
}

void new()
{
    connection = new System.Data.OleDb.OleDbConnection();
    command = new System.Data.OleDb.OleDbCommand();
}

Прежде чем начать работать с классом нужно создать и открыть подключение к источнику данных, для этого нужно задать строку подключения. Строка подключения состоит из поставщика данных (Provider), в нашем случае это Microsoft.Jet.OLEDB.4.0, места расположения источника данных (Data Source) и расширенных свойств (Extended Properties), в нашем случае это тип источника данных dBase IV.

public boolean openConnection(str _directory = WinAPI::getTempPath())
{
    boolean ret = true;
    str path = strFmt("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%1;Extended Properties=dBase IV", _directory);
    System.String pathDB = path;
    CLRInterop object;
         
    try
    {
        connection.set_ConnectionString(pathDB);
        connection.Open();
        command.set_Connection(connection);
    }
    catch
    {
        object = CLRInterop::getLastException();
        error(object.ToString());
        ret = false;
    }
         
    return ret;
}

Создание и заполнение dbf таблицы выполняется посредством SQL запросов выполняемых с источником данных, для этого нужно создать метод выполнения запросов.

private boolean executeQuery(str _query)
{
    boolean ret = true;
    System.String query = _query;
    CLRInterop object;
         
    command.set_CommandText(query);
         
    try
    {
        command.ExecuteNonQuery();
    }
    catch
    {
        object = CLRInterop::getLastException();
        error(object.ToString());
        ret = false;
    }
         
    return ret;
}

Чтобы создать саму dbf таблицу нужно создать метод при помощи которого будет сформирован SQL запрос создания таблицы. На вход данного метода подаем строковую переменную _name где указываем наименование таблицы и коллекцию _listEnum где содержится информация о полях таблицы. В коллекции мы храним контейнеры со следующей структурой:

— первый элемент – это название поля,

— второй элемент – это тип поля,

— третий элемент – это длина строки либо количество знаков до запятой,

— четвертый элемент – это количество знаков после запятой.

public boolean createTableExecuteQuery(str _name, ListEnumerator _listEnum)
{
    str query, columns;
    Types type;
    str name, beforeComma, afterComma;
    boolean ret = false;
                
    if (_name)
    {
        while (_listEnum.moveNext())
        {
            if (typeOf(_listEnum.current()) == Types::Container)
            {
                [name, type, beforeComma, afterComma] = _listEnum.current();
                columns += columns ? ", " : "";
                columns += name + " ";
                switch (type)
                {
                    case Types::Real: columns += strFmt("decimal(%1, %2)", beforeComma, afterComma); break;
                    case Types::Date: columns += "date"; break;
                    case Types::String:
                    default: columns += strFmt("nvarchar(%1)", beforeComma);
                }
            }
        }
         
        if (columns)
            query = strFmt("CREATE TABLE %1 (%2)", _name, columns);
         
        if (query)
            ret = this.executeQuery(query);
    }
         
    return ret;
}

Когда уже таблица создана то можно начать ее заполнять. Для этого нужно создать метод который сформирует SQL запрос для вставки данных в таблицы. Входные данные здесь используется те же что и для метода создания таблицы createTableExecuteQuery.

public boolean insertExecuteQuery(str _name, ListEnumerator _listEnum)
{
    str query, columns, values;
    str name;
    anytype value;
    boolean ret = false;
         
    if (_name)
    {
        while (_listEnum.moveNext())
        {
            if (typeOf(_listEnum.current()) == Types::Container)
            {
                [name, value] = _listEnum.current();
                columns += columns ? ", " + name : name;
                value = typeOf(value) == Types::Date || typeOf(value) == Types::String ? strFmt("'%1'", value) : strFmt("%1", value);
                values += values ? ", " + value : value;
            }
        }
         
        if (columns)
            query = strFmt("INSERT INTO %1 (%2) values (%3)", _name, columns, values);
         
        if (query)
            ret = this.executeQuery(query);
    }
         
    return ret;
}

Вот и все, теперь с помощью этого класса можно создать и заполнить dbf таблицу. В случае если нужно будет отредактировать в ней данные или ее вовсе удалить, то не сложно дописать свои методы для этих целей, но нужно знать синтаксис SQL чтобы правильно построить запросы.

Comments

So empty here ... leave a comment!

Добавить комментарий

Sidebar