Как в делфи сохранить таблицу в файл

Обновлено: 07.07.2024

Ваш объект, тип, или запись должна быть разбита на простые составляющие и впоследствии записаны в файл. Как это делается. Например строковую переменную можно записать в файл следующим образом:

procedure WriteToFile(var F: file; const str: string); var Len: LongInt; begin Len := Length(str); BlockWrite(F, Len, SizeOf(Len)); if Len > 0 then begin BlockWrite(F, Str[1], Length(Str) * SizeOf(Str[1])); end; end;

procedure WriteToFile(var F: file; const Int: Integer); var LInt: LongInt; begin LInt := Int; BlockWrite(F, LInt, SizeOf(LInt)); end;

Как видите при сохранении целого числа мы приводим его сначала к типу LongInt. Это делается по причине того, что тип Integer может изменяться в зависимости от версии Delphi, а также насколько я помню от конфигурации операционной системы. Точнее не сам тип, а способ его представления в памяти компьютера. В общем LongInt это фиксированный целый тип со знаком, который не будет изменяться в будущих выпусках Delphi.

Теперь если вы захотите сохранить в файл динамический массив целых чисел, можно воспользоваться следующей процедурой:

procedure WriteToFile(var F: file; const IntegerArray: TIntArray); var i: Integer; Len: LongInt; begin Len := Length(IntegerArray); BlockWrite(F, Len, SizeOf(Len)); if Len > 0 then begin for i := Low(IntegerArray) to High(IntegerArray) do begin WriteToFile(F, IntegerArray[i]); end; end; end;

Ниже показано как можно сохранить в ваш файл изображение в формате JPEG. Важно понимать, что даже если в файл будет сохранено одно только изображение, редактором оно уже не откроется, нужно будет извлекать его из файла таким же образом. Именно поэтому данный способ сохранения подходит только для составных типов. Например когда вы хотите сохранить картинку вместе с какой то информацией:

procedure WriteToFile(var F: file; const Image: TJPEGImage); var Len: LongInt; ImageStream: TBytesStream; begin ImageStream := TBytesStream.Create; Image.SaveToStream(ImageStream); Len := Length(ImageStream.Bytes); BlockWrite(F, Len, SizeOf(Len)); BlockWrite(F, ImageStream.Bytes[0], Len); ImageStream.Free; end;

И в конце, как обещал общая процедура сохранения в файл например массива целых чисел и изображения в формате Jpeg:

procedure Save(const FileName: string; const IntegerArray: TIntArray; const Image: TJPEGImage); var F: file; begin Result := False; AssignFile(F, FileName); Rewrite(F, 1); try WriteToFile(F, IntegerArray ); WriteToFile(F, Image ); finally CloseFile(F); end; end;

В процедуру передается имя файла, динамический массив целых чисел и изображение в формате Jpeg. Как видите все просто. Главное помните, что чтение всех данных должно происходить строго в том же порядке, что и запись. Для удобства метод WriteToFile я делаю перегруженным, и в зависимости от типа переданного аргумента, компилятор сам выбирает метод сохранения в файл. Пример достаточно примитивен, но отражает суть процесса в целом. Например можно было создать запись состоящую из массива целых чисел и картинки, реализовать WriteToFile для нее и использовать в дальнейшем. Примерно вот так:

Приступим к программированию пунктов меню Открыть, Сохранить, Сохранить как…, Выход.

Нам понадобится общая переменная fFilePath типа String для всех процедур, которая будет хранить полный путь к открытому файлу. Опишем ее в разделе var перед ключевым словом implementation следующим образом :


Такой способ описания позволяет сразу «обнулить» нашу переменную.

Теперь опишем процедуру открытия файла с помощью диалога выбора файла. Для этого на форме в режиме разработки, щелкните по Файл-Открыть


После чего откроется редактор кода с созданной процедурой TForm1.fOpenClick

В нее необходимо поместить следующий код:

if fOpenDialog.Execute then
begin
fFilePath:=fOpenDialog.FileName;
txt.Lines.LoadFromFile(fFilePath);
end;

Функция Execute диалога fOpenDialog открывает окно выбора файла. При выборе файла и нажатия кнопки Открыть, функция возвращает True, если нажата кнопка Отмена, то false. Обратите внимание, диалог вызывается с использование условия if, т.е. мы проверяем результат выполнения Execute.Если результат Истина, то мы продолжаем открытие файла, если Иначе, то ничего не происходит. Если не сделать такую проверку, диалог сработает при выборе файла, но если пользователь откажется открывать файл и нажмет Отмена, выскочит ошибка т.к. txt.Lines.LoadFromFile попытается открыть файл, который не выбран.

В данной процедуре мы присваиваем переменной fFilePath, полный путь к выбранному файлу вида «x:\mytxt\txtFile.txt», который возвращает функция FileName диалога fOpenDialog и загружаем текст в txt.

Вот и все открытие файла.

Далее пункт «Сохранить как…».

Так же кликаем по данному пункту и в созданной процедуре TForm1.fSaveAsClick пишем код:

if fFilePath='' then fsavedialog.FileName:='Новый документ.txt'
else fsavedialog.FileName:=fFilePath;

if fSaveDialog.Execute then
begin

if extractfileext(fSaveDialog.FileName)='' then
fFilePath:=fSaveDialog.FileName+'.txt'
else fFilePath:=fSaveDialog.FileName;

txt.Lines.SaveToFile(fFilePath);
end;

Эта процедура посложнее. Объясню ее работу:

Первое условие IF – это по сути украшение, проверяет переменную fFilePath и если она пуста, то в поле указания имени файла выведет имя по умолчанию «Новый документ.txt». Переменная fFilePath пуста только в том случае, если мы будем создавать документ, а не открывать его для редактирования. Если же переменная fFilePath не пуста, то будет выведено имя файла, который был открыт.

Второе условие IF – выполняет запуск диалога сохранения.

Третье условие IF – проверяет, имеет ли введенное имя файла расширение, если введено просто имя файла без его расширения, то к имени добавляется «.txt». Функция extractfileext извлекает из полного имени файла его расширение. Например, файл «Мой блокнот.txt», функция вернет его расширение «txt». Если не сделать данную проверку и присоединение расширения, то будет создан файл без указанного расширения, и в системе он будет не опознанным. Если же оставить только присоединение расширения и при этом имя файла будет «Мой блокнот.txt», то к имени будет добавлено еще расширение «txt», в результате получим файл «Мой блокнот.txt.txt».

Теперь пункт «Сохранить». Обратите внимание, во всех редакторах, если создать новый документ и нажать на «Сохранить», то будет открыт диалог «Сохранить как», если же документ открыт для редактирования, то происходит просто сохранение изменений. Реализуем тоже самое в нашем блокноте.

Создаем процедуру TForm1.fSaveClick вышеуказанным способом и пишем следующий код:

if fFilePath='' then fSaveAs.Click
else txt.Lines.SaveToFile(fFilePath);

т.е. мы проверяем переменную fFilePath, если она пуста, то вызываем процедуру пункта меню «Сохранить как…» - fSaveAs. По сути, мы программно «нажимаем» на пункт меню «Сохранить как…». Если же файл был открыт, то просто сохраняем изменения в файл.

И последний пункт меню «Выход».

Команда данного пункта проста и однострочна:

Вот так выглядит полный листинг нашей программы (по основным пунктам я расставил комментарии). Исходники и скомпилированный проект в прикрепленном архиве.

unit exNotepad;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Menus;

type
TForm1 = class(TForm)
txt: TMemo;
MainMenu1: TMainMenu;
N1: TMenuItem;
fOpen: TMenuItem;
fSave: TMenuItem;
fSaveAs: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
fOpenDialog: TOpenDialog;
fSaveDialog: TSaveDialog;
procedure fOpenClick(Sender: TObject);
procedure fSaveAsClick(Sender: TObject);
procedure fSaveClick(Sender: TObject);
procedure N3Click(Sender: TObject);

private

public

end;

var
Form1: TForm1;
fFilePath: string = '';

implementation

procedure TForm1.fOpenClick(Sender: TObject);
begin
//запуск диалога открытия файла
if fOpenDialog.Execute then
begin
fFilePath:=fOpenDialog.FileName;
txt.Lines.LoadFromFile(fFilePath);
end;
end;

procedure TForm1.fSaveAsClick(Sender: TObject);
begin
//если fFilePath пусто, то выводим имя по умолчанию
if fFilePath='' then fsavedialog.FileName:='Новый документ.txt'
// если fFilePath не пусто
else fsavedialog.FileName:=fFilePath;

//запуск диалога сохранения
if fSaveDialog.Execute then
begin

//проверяем есть ли расширенеие у заданного файла
//если нет, то задаем .txt
if extractfileext(fSaveDialog.FileName)='' then
fFilePath:=fSaveDialog.FileName+'.txt'
//если есть, то оставляем
else fFilePath:=fSaveDialog.FileName;

//сохраняем файл
txt.Lines.SaveToFile(fFilePath);
end;
end;

procedure TForm1.fSaveClick(Sender: TObject);
begin
//если fFilePath пуста то открывает диалог сохранения
if fFilePath='' then fSaveAs.Click
//иначе просто сохраняем открытый файл
else txt.Lines.SaveToFile(fFilePath);
end;

procedure TForm1.N3Click(Sender: TObject);
begin
form1.Close;
end;

end.

П.С. Для того чтоб при открытии текста, появились полосы прокрутки у объекта Memo (txt) необходимо указать свойство ScrollBars = ssBoth.


Прикрепленный файл: exNotepad v1.1.zip

При написании бизнес приложений на Delphi, выполняющих какие либо расчеты, может возникнуть необходимость импорта (экспорта) данных из файлов других приложений. Одно из основных таких приложений – MS Excel. Как прочитать файлы xls в Delphi мы сейчас и рассмотрим!?

Создадим новый проект и разместим на форме три компонента:

StringGrid – находится на палитре компонентов, во вкладке Additional

stringgrid в delphi

Кнопку Button и для удобства выбора файлов, диалог открытия файлов (работа с диалогами описана здесь).

Для StringGrid, в свойствах(Properties) укажем следующее:
DefaultRowHeight – 17
FixedCols – 0
FixedRows – 0

В результате форма будет выглядеть примерно так:


На этом украшательства закончим и приступим к написанию кода.

Для работы с Excel файлами нам понадобится библиотека ComObj, входящая в стандартную поставку Delphi. Подключается она в разделе Uses. Добавьте в конце, после запятой «ComObj».


Теперь опишите процедуру Xls_Open после ключевого слова implementation:

procedure Xls_Open(XLSFile:string; Grid:TStringGrid);
const
xlCellTypeLastCell = $0000000B;
var
ExlApp, Sheet: OLEVariant;
i, j, r, c:integer;

begin
//создаем объект Excel
ExlApp := CreateOleObject('Excel.Application');

//делаем окно Excel невидимым
ExlApp.Visible := false;

//открываем файл XLSFile
ExlApp.Workbooks.Open(XLSFile);

//создаем объект Sheet(страница) и указываем номер листа (1)
//в книге, с которого будем осуществлять чтение
Sheet := ExlApp.Workbooks[ExtractFileName(XLSFile)].WorkSheets[1];

//активируем последнюю ячейку на листе
Sheet.Cells.SpecialCells(xlCellTypeLastCell, EmptyParam).Activate;

// Возвращает номер последней строки
r := ExlApp.ActiveCell.Row;

// Возвращает номер последнего столбца
c := ExlApp.ActiveCell.Column;

//устанавливаем кол-во столбцов и строк в StringGrid
Grid.RowCount:=r;
Grid.ColCount:=c;

//считываем значение из каждой ячейки и копируем в нашу таблицу
for j:= 1 to r do
for i:= 1 to c do
Grid.Cells[i-1,j-1]:= sheet.cells[j,i];
//если необходимо прочитать формулы то
//Grid.Cells[i-1,j-1]:= sheet.cells[j,i].formula;

//закрываем приложение Excel
ExlApp.Quit;

//очищаем выделенную память
ExlApp := Unassigned;
Sheet := Unassigned;

end;

Наша процедура Xls_Open имеет два входных параметра:

  1. XLSFile – путь к файлу Excel (xls)
  2. Grid – таблица, в которую будем осуществлять вывод данных.

В комментариях к коду я постарался все расписать, объясню немного принцип работы процедуры.

Мы создаем в памяти объект ExlApp с приложением Excel.Application. Затем указываем что этот объект будет невидим для пользователя ExlApp.Visible := false (если false заменить на true, то при открытии файла мы увидим окно Excel с открываемым файлом). Далее открывается файл ExlApp.Workbooks.Open(XLSFile). Потом создаем еще один объект Sheet, который позволяет работать с листом книги Excel: Sheet := ExlApp.Workbooks[ExtractFileName(XLSFile)].WorkSheets[1]. Единица в конце указывает номер листа с которого будем читать данные (к листам можно обращаться по имени, для этого вместо 1 указываем «ИмяЛиста1»). Далее определяем кол-во строк и столбцов которые содержат данные, и используя циклы For считываем данные копируя их в StringGrid. Впринципе и все.

Для использования процедуры Xls_Open пропишем в событие Click кнопки Button1 следующее:

If OpenDialog1.Execute then Xls_Open (OpenDialog1.FileName, StringGrid1);

Основные недостатки этого способа: медленное чтение данных (хотя для небольших файлов вполне сгодится) и необходимость установленной версии Excel на компьютере пользователя.

Полный листинг программы:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, StdCtrls,ComObj;

type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
Button1: TButton;
OpenDialog1: TOpenDialog;
procedure Button1Click(Sender: TObject);
private

public

end;

var
Form1: TForm1;

implementation

procedure Xls_Open(XLSFile:string; Grid:TStringGrid);
const
xlCellTypeLastCell = $0000000B;
var
ExlApp, Sheet: OLEVariant;
i, j, r, c:integer;

begin
//создаем объект Excel
ExlApp := CreateOleObject('Excel.Application');

//делаем окно Excel невидимым
ExlApp.Visible := false;

//открываем файл XLSFile
ExlApp.Workbooks.Open(XLSFile);

//создаем объект Sheet(страница) и указываем номер листа (1)
//в книге, с которого будем осуществлять чтение
Sheet := ExlApp.Workbooks[ExtractFileName(XLSFile)].WorkSheets[1];

//активируем последнюю ячейку на листе
Sheet.Cells.SpecialCells(xlCellTypeLastCell, EmptyParam).Activate;

// Возвращает номер последней строки
r := ExlApp.ActiveCell.Row;

// Возвращает номер последнего столбца
c := ExlApp.ActiveCell.Column;

//устанавливаем кол-во столбцов и строк в StringGrid
Grid.RowCount:=r;
Grid.ColCount:=c;

//считываем значение из каждой ячейки и копируем в нашу таблицу
for j:= 1 to r do
for i:= 1 to c do
Grid.Cells[i-1,j-1]:= sheet.cells[j,i];
//если необходимо прочитать формулы то
//Grid.Cells[i-1,j-1]:= sheet.cells[j,i].formula;

//закрываем приложение Excel
ExlApp.Quit;

//очищаем выделенную память
ExlApp := Unassigned;
Sheet := Unassigned;

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
If OpenDialog1.Execute then Xls_Open (OpenDialog1.FileName, StringGrid1);
end;

end.

Обновленный пример. Добавлена функция отбора строк по критерию. Так же добавлен обработчик делающий отображение шрифта "шапки" в StringGrid жирным. Все дополнения постарался по максимуму раскомментить

file-bd_2

Всем привет ребята! Продолжаем рассматривать работу с базами данных в Delphi. Сегодня мы начнем рассматривать базы данных, которые работают на файлах. Да, сейчас базы данных на файлах не настолько популярны, но раньше они расправлялись с хорошим объемом информации, да и сейчас они применяются, я так думаю, где необходимо использовать базу данных небольшого объема.

Естественно, базу данных на файлах можно отнести к файловой модели сервера, если использовать ее как сетевую. Такая модель сервера имеет ряд недостатков:

  • Будет большой сетевой трафик: передаваться по сети будет множество файлов, блоков информации и так далее
  • Для доступа к данным мы можем использовать только лишь файловые команды
  • Защиту базы данных мы можем производить только лишь на уровне файловой системы

Конечно, если у Вас база данных рассчитана на одного пользователя, то с легкостью можно использовать базу данных, основанную на файлах. Файловую базу данных, в некоторых случаях также удобно использовать, так как нет необходимости покупать дорогие СУБД, а также их потом администрировать, хотя в настоящее время, во время высоких технологий, больших объемов информации, а также больших сетей, не использовать СУБД просто невозможно.

Раньше, на сколько я знаю, 1С:Предприятие работало на файловых базах данных, хотя, наверное, и сейчас там они встроены, так что как видите, крупные проекты до сих пор используют такую модель данных.

Для организации файловой базы данных нам поможет компонент TClientDataSet, который располагается на вкладке DataAccess. Поэтому, создаем проект в Delphi и устанавливаем на форму компонент TClientDataSet. В данном компоненте есть замечательное свойство – FieldDefs, с помощью которого мы можем создавать список полей, в которых будут храниться данных, их размер, а самое главное тип. Для того чтобы создать список полей, нам необходимо нажать на свойство FieldDefs и с помощью встроенного редактора задать список полей, хотя это можно сделать с помощью кода. С помощью встроенного редактора создаем нашу будущую базу данных со списком полей, их типом, а также размером.

Базу данных можете придумать любую, например база студентов и их номеров телефонов. У меня получились следующие поля:

Итак, пройдемся по полям:

  • ID – имеет тип ftAutoInc
  • Name – имеет тип ftString
  • Phone – имеет тип fsString

Сам тип задается в свойстве DataType, а размер поля, если это так важно, то он задается в свойстве Size.

Теперь нам необходимо создать пустой набор данных в памяти компьютера. Для этого можно нажать правой кнопкой мыши по компоненту TClientDataSet и нажать на пункт контекстного меню – Create Dataset, то есть создать набор данных. Мы также можем создать данный набор с помощью процедуры:

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

  • Save to MyBase Xml Table… (это сохранить таблицу в файл формата XML)
  • Save to MyBase Xml UTF8 Table… (это сохранить таблицу в файл формата XML и в кодировке UTF8)
  • Save to binary MyBase file… (это сохранить таблицу в бинарный файл)

Я сохранил таблицу в формате XML, а также кодировке UTF8. Кроме этого таблицу можно сохранить и программным методом, с помощью процедуры SaveToFile, то об этом мы поговорим уже в следующей статье. Сам XML-файл у меня получился следующей структуры:

file-bd_1

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

Читайте также: