Delphi экспорт базы в xml
Работа с файловыми базами данных в Delphi. Часть 2
Всем привет! Ну что, продолжаем рассматривать работу с файловыми базами данных в Delphi. Мы закончили прошлую статью на том, что мы сохранили нашу БД в XML-формат. Но не стоит забывать о том, что сохранять структуру таблицы, а также ее содержимое можно не только в файл, но и в поток памяти.
Как я говорил в прошлой статье, мы можем сохранить в файл с помощью контекстного меню, нажав по компоненту TClientDataSet правой кнопкой мыши. Но лучше воспользоваться методом, для сохранения в файл:
Procedure SaveToFile(const FileName:string; Format:TDataPacketFormat);
Либо же методом для сохранения в поток памяти:
Procedure SaveToStream(Stream:TStream; Format:TDataPacketFormat);
Первый параметр предполагает имя файла или поток, в которой будет сохранена структура таблицы, а также сами данные, а второй параметр в методах определяет формат сохраняемых данных, который может принимать следующие значения:
Значение параметра | Описание | Расширение файла |
dfBinary | Бинарный формат данных | *.cds |
dfXML | XML формат | *.xml |
dfXMLUTF8 | Также XML формат, только текст сохраняется в кодировке UTF-8 | *.xml |
Так, с методами сохранения таблиц мы разобрались, теперь давайте же рассмотрим методы, которые позволяют нам загрузить таблицу сразу из файла, либо же из потока памяти:
Procedure LoadFromFile(const FileName:string);
Выше метод для загрузки из файла, а что касается метода для загрузки из потока памяти, то он выглядит следующим образом:
Procedure LoadFromStream(Stream:TStream);
Ну что, теперь давайте попробуй сохранить структуру таблицы в файл. Пока что только структуру таблицы, так как мы ее не заполняли никакими данными. Итак, давайте для начала создадим не большой проект и поместим на форму следующие компонента:
- TButton
- TClientDataSet – на вкладке Data Access
- TSaveDialog
Поэтому, на событие кнопки Onclick мы напишем примерно следующий код:
Давайте дополним наш проект следующими компонентами:
- TDataSource – расположен на вкладку Data Access
- TOpenDialog
- TButton
- TDBGRid
Давайте разбираться немного. Компонент TDataSource нам необходим, как источник данных. Компонент TOpenDialog нам необходим для того чтобы загружать в наш проект файловую базу данных. Компонент TButton понятно для чего – для загрузки, по нажатию на кнопку мы будем загружать файл в проект, ну и компонент TDBGRid нам необходим для отображения данных нашей файловой БД. Но так как данных у нас пока нет, будут отображаться просто поля.
Для начала нам необходимо связать компоненты. Поэтому, выделяем компонент TDataSource и в свойстве DataSet выбираем компонент TClientDataSet. Далее выделяем компонент TDBGrid и в свойстве DataSource, выбираем наш компонент TDataSource.
Почти все, нам теперь необходимо загрузить наш XML-файл в проект. Для этого на событие OnClick нашей кнопки пишем следующий код:
В самом конце мы активируем наш набор данных, и он должен отобразиться в компоненте TDBGRid. У меня отобразились только лишь название полей, так как данных у меня нет. Вы же можете немного поэкспериментировать с сегодняшней статьей, ну а в следующей статье мы рассмотрим необходимую структуру XML-файла, чтобы он корректно отображался в нашем проекте, а также рассмотрим то, как можно добавлять, редактировать, удалять данные из файловой базы данных.
У меня после загрузки XML-файла, проект выглядит следующим образом:
Delphi экспорт базы в xml
Имеется код программы. Экспортирование содержимого таблицы Dbgrid в Exel проходит нормально. Необходимо экспортировать в html и xml, то есть добавить ещё пару кнопок с запрограммированным кодом. Как правильно сделать?
Код программы:
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, ADODB, Grids,DBGrids,ComObj,ActiveX;
type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
ComboBox1: TComboBox;
ADOQuery2: TADOQuery;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
Button1: TButton;
ComboBox2: TComboBox;
Edit1: TEdit;
ADOQuery3: TADOQuery;
DataSource2: TDataSource;
DBGrid2: TDBGrid;
ADOQuery4: TADOQuery;
Button3: TButton;
Edit2: TEdit;
Label2: TLabel;
Button2: TButton;
Label1: TLabel;
Button4: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure ComboBox1Change(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
var
Form1: TForm1;
procedure TForm1.FormCreate(Sender: TObject);
var str:string;
begin
ADOQuery1.First ;
ComboBox1.Items.Clear;
ComboBox1.Items.Add(‘Âèä òîâàðà’);
ComboBox1.ItemIndex := 0;
while not ADOQuery1.Eof do
begin
Str :=ADOQuery1.FieldByName(‘TypeName’) .AsString;
ComboBox1.Items.Add(str);
ADOQuery1.Next;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Sum:real;
Values, ID, Marka, Firm, Pokupatel, Zena, Kol :string;
begin
).AsStrin g;
Marka := »» + ADOQuery2.FieldByName(‘Marka’).AsSt ring + »»;
Firm := »» + ADOQuery2.FieldByName(‘Firm’).AsStr ing + »»;
Pokupatel := »» + ComboBox2.Text + »»;
Zena := ADOQuery2.FieldByName(‘Zena’).AsStr ing;
Kol := Edit1.Text;
ADOQuery4.SQL.Clear;
ADOQuery4.SQL.Add(‘INSERT INTO Pokupki (ID, Marka, Firm, Pokupatel, Zena, Kol) ‘);
Values := ‘VALUES (‘ + ID + ‘, ‘
+ Marka + ‘, ‘
+ Firm + ‘, ‘
+ Pokupatel + ‘, ‘
+ Zena + ‘, ‘
+ Kol + ‘)’ ;
ADOQuery4.SQL.Add(Values);
ADOQuery4.ExecSQL;
Sum := 0;
while not ADOQuery3.Eof do
begin
Sum := Sum + ADOQuery3.FieldByName(‘Zena’).AsFlo at * ADOQuery3.FieldByName(‘Kol’).AsFloa t;
ADOQuery3.Next;
end;
Edit2.Text := FloatToStr(Sum);
end;
procedure TForm1.Button3Click(Sender: TObject);
var Sum :real;
ID:string;
begin
).AsStrin g;
ADOQuery4.SQL.Clear;
ADOQuery4.SQL.Add(‘DELETE FROM Pokupki WHERE > ADOQuery4.ExecSQL;
Sum := 0;
while not ADOQuery3.Eof do
begin
Sum := Sum + ADOQuery3.FieldByName(‘Zena’).AsFlo at * ADOQuery3.FieldByName(‘Kol’).AsFloa t;
ADOQuery3.Next;
end;
Edit2.Text := FloatToStr(Sum);
end;
procedure TForm1.ComboBox1Change(Sender: TObject);
Var CurID:integer;
begin
ADOQuery2.Close;
ADOQuery2.SQL.Clear;
ADOQuery2.SQL.Add(‘Select * From Device ‘);
if ComboBox1.ItemIndex>0 then
begin
ADOQuery2.SQL.Add(‘WHERE Type />TypeID’);
ADOQuery1.Locate(‘TypeName’, ComboBox1.Text,[]);
Cur ).AsInteger;
ADOQuery2.Parameters.ParamByName(‘p Type > end;
ADOQuery2.Open;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
i,j,index: Integer;
ExcelApp,sheet: Variant;
begin
ExcelApp := CreateOleObject(‘Excel.Application’ );
ExcelApp.Visible := False;
ExcelApp.WorkBooks[1].WorkSheets[1].name := ‘Export’;
sheet:=ExcelApp.WorkBooks[1].WorkSheets[‘Export’];
Sheet.Cells[1,1]:=’¹’;
Sheet.Cells[1,2]:=’Ìàðêà’;
Sheet.Cells[1,3]:=’Ôèðìà’;
Sheet.Cells[1,4]:=’Ïîêóïàòåëü’;
Sheet.Cells[1,5]:=’Öåíà’;
Sheet.Cells[1,6]:=’Êîëè÷åñòâî’;
for i:=1 to ADOQuery3.RecordCount do
begin
for j:=1 to ADOQuery3.FieldCount do
sheet.cells[index,j]:=ADOQuery3.Fields[j-1].asstring;
inc(index);
ADOQuery3.Next;
end;
ExcelApp.Visible := true;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
Экспорт таблиц MS SQL Server 2000/2005/2008 в XML файл
Здравствуйте, уважаемое хабрасообщество !
Поговорим о проблеме, ставшей заголовком этой темы.
Постановка:
Необходимость вывода таблицы на сервере в XML файл нужной кодировки для дальнейших нужд (анализ, включение XML в другие компоненты и приложения и т.п.). Будем использовать bat-сценарий.
Возникшие трудности
SQL Server не сохраняет кодировку XML, если XML-данные постоянно хранятся в базе данных. Поэтому оригинальная кодировка полей XML недоступна при экспорте XML-данных. Для экспорта данных SQL Server использует кодировку UTF-16.
©
Простота и скорость использования для различных таблиц и баз.
Шаги реализации
Для начала, воспользуемся утилитой bcp, которая входит в комплект поставки MS SQL Server (Даже в Express версии). Подробрее.
Из ее возможностей нам понадобится только вывод результата запроса в файл.
Значения ключей на примере:
bcp «SELECT * FROM DB.SCHEMA.TABLE FOR XML AUTO, ROOT(‘ROOT’)» queryout temp.xml -w -S %SERVERNAME% -U %DBUSER% -P %DBPASS%
SELECT запрос для выборки всех данных из таблицы (указывается полное имя).
XML AUTO отвечает за преобразование результата в XML дерево.
ROOT назначает корневой элемент в этом дереве
queryout задает выходной файл
-w задает использование юникода для массового копирования
-S имя экземпляра сервера
-P пароль
-U пользователь
Этой командой мы получим XML файл БЕЗ заголовка в кодировке UTF-16.
Нужно присоединить заголовок и сделать xml нужной кодировки.
Создадим шаблон заголовка xml_header.xml с содержимым:
* This source code was highlighted with Source Code Highlighter .
Теперь достаточно будет выполнить команду
copy xml_header.xml + bcp_out.xml result.xml
и получить валидный XML документ.
Для преобразования кодировки же будем использовать iconv, любой реализации. Я выбрал самое компактное и портативное решение под Windows, написанное на Win32 API от Yukihiro Nakadaira.
Итак, файл сценария:
if «%1» == «» (
rem Отсутстуют параметры
echo Use with : db_name db_table [out_file]
exit /b 1
)
if «%2» == «» (
echo Use with : db_name db_table [out_file]
exit /b 1
)
rem Читаем настройки из файла settings.txt, который должен располагаться в
rem том же каталоге, что и bat-файл. Если не удалось распарсить настройки —
rem выходим с ненулевым кодом возврата.
call :read_settings %
dp0settings.txt || exit /b 1
set DBNAME=%1
set DBTABLE=%2
set OUTFILE=%3
echo;
echo ====== ECHO SETTINGS FROM CONFIG ======
echo;
echo ServerName : %SERVERNAME%
echo Schema : %SCHEMA%
echo Out codepage: %OUTCP%
echo User : %DBUSER%
echo Pass : ********
echo Iconv path : %ICONVPATH%
echo;
echo =======================================
echo;
echo ====== ECHO SETTINGS FROM CMD =========
echo;
echo DB Name = %1
echo DB Table = %2
echo Output file = %3
echo;
echo =======================================
echo;
echo ====== CALL TO BCP UTIL ===============
echo;
call :bcp_call
echo;
echo ====== CALL TO ICONV ==================
echo;
call :iconv_call
echo;
echo =======================================
echo;
echo See the loglog.txt for details
exit /b 0
rem
rem Функция для чтения настроек из файла.
rem Вход:
rem %1 — Имя файла с настройками
:read_settings
rem Проверка существования файла
if not exist %SETTINGSFILE% (
echo FAIL: No such file %SETTINGSFILE%
exit /b 1
)
rem Обработка файла c настройками
for /f «eol=# delims== tokens=1,2» %%i in (%SETTINGSFILE%) do (
set %%i=%%j
)
rem
rem Функция для обращения к БД
:bcp_call
bcp «SELECT * FROM %DBNAME%.%SCHEMA%.%DBTABLE% FOR XML AUTO, ROOT(‘%DBTABLE%’)» queryout temp.xml -w -r «» -S %SERVERNAME% -U %DBUSER% -P %DBPASS% > lograwlog.txt
rem Кодируем лог в нормальную кодировку
%ICONVPATH% -f cp866 -t cp1251 lograwlog.txt > loglog.txt
del lograwlog.txt
copy lib xml_header.xml + temp.xml temp2.xml > nul
del temp.xml
rem
rem Функция перекодировки
:iconv_call
rem Дефолтное значение выходной кодировки
if «%OUTCP%» == «» (
set OUTCP=CP1251
)
rem Дефолтное значение выходного файла
if «%OUTFILE%» == «» (
set OUTFILE=out%DBTABLE%.xml
)
if not exist %ICONVPATH% (
echo FAIL: Check Iconv path !
exit /b /1
)
%ICONVPATH% -f UTF-16 -t %OUTCP% temp2.xml > %OUTFILE%
del temp2.xml
* This source code was highlighted with Source Code Highlighter .
Через параметры командной строки передаем: имя_базы имя_таблицы [выходной файл]
Остальную конфигурацию прописываем в settings.txt:
# Имя сервера
SERVERNAME=WINDSQLEXPRESS
# Имя схемы
SCHEMA=dbo
# Имя выходной кодировки
OUTCP=CP1251
# Имя пользователя
DBUSER=dzhon
# Пароль пользователя
DBPASS=123
#Путь к iconv.exe
ICONVPATH=libwin_iconv.exe
Для логики, в XML файле создано 3 функции.
Первая парсит конфигурацию, вторая вызывает bcp, третья — iconv для результирующего файла.
Заключение
Сразу замечу, что по-умолчанию используется CP1251 и лог работы bcp кодируется в нее же. Сделано это для удобства работы именно в Windows, а не каких-то иных религиозных предпочтений. Помню времена, когда Windows XP выдавала крокозябры при вызове простого route PRINT в описаниях интерфейсов… Поэтому я сам и предпочитаю всегда и везде UTF-8. Впрочем, скрипт достаточно гибок к замене кодировки выхода, правда придется задать в xml_header.xml другое значение.
Скачать архив с рабочим вариантом решения можно здесь (13 Кб).
Для SQL Server 2000 придется внести некоторые изменения, в связи с тем, что понятие схемы (в смысле контейнера объектов) было введено только с 2005-го.
Вы можете также посмотреть материал по написанию bat файлов, из которого была утащена функция парсинга конфигурации.
Спасибо за внимание, надеюсь, кому-то поможет.
Перенесу в тематический блог при наличии кармы, впрочем, решать вам.