Предистория
Как известно прогресс не стоит на месте, все течет и развивается. Вот так в очередной раз прогресс стукнул по лбу в виде задачи перевести текущий проект на новую базу данных MS Access 2007 и обязательно нужно использовать его новые возможности в виде полей типа «Attachments».
История
Волею судеб я с самого начала писал программы на Delphi, так мне казалось и быстрее и удобнее. Так что портировать проект мне тоже пришлось на Delphi. Для начала я решил выяснить что ж это за такой тип данных и как с ним бороться. После недолгих поисков, ковыряния во встроенном в Access Basicа выяснилось, что это новый тип данных, который представляет собой что-то вроде вложенной в поле таблицы данных (в ней такие поля: айдишник строки, имя файла, и собственно сам файл и еще что-то, кому интересно открываете Access и смотрите). Например: пользователь добавляет строку в таблицу с именем автора книг, его данными и добавляет поле Attachment, и в этом поле загружает 25 книг автора и одно его видео ну и парочке аудиокниг.
И суть задачи в том, чтобы для конкретного автора вытащить и сохранить на диск вот эти парочку аудиокниг и одно видео.
Книг и информации про это маловато, поэтому собрав на основе всего найденного свое решение я остался доволен.
Итак что нам понадобится:
- Delphi;
- Импортированный файл DAO_TLB.pas;
- Прямые руки;
Начнемс.
Подключение к базе данных через DAO
Декларируем такие переменные, они нам потребуются для наших операций. Я их подключал в разделе public
Также не забываем подключить наш юнит DAO_TLB.pas.
public
att : Recordset2;
DAO: _DBEngine;
db: DAO_TLB.Database;
MyTable: Recordset2;
Далее функция подключения к базе:
procedure TForm1.ConnectviaDAO;
begin
if (length(databasename)=0) or not FileExists(databasename) then
if OpenDialog1.Execute then
databaseName := OpenDialog1.FileName;
TableName := 'Table1';
//указываем файл базы данных и имя нашей таблицы. У меня в таблице было всего два поля, айдишник и атачментс.
V120 := 'DAO.DBEngine.120'; // указываем версию движка, который будем использовать
SetCurrentDir(ExtractFileDir(Application.ExeName));
try
try
ClassID := ProgIDToClassID(v120);
except
end;
DAO := CreateComObject(ClassID) as _DBEngine; // создаем COM объект с указанием его типа
db := DAO.OpenDatabase(DatabaseName, true, false, ''); // открываем базу данных
MyTable :=Recordset2(db.OpenRecordset(TableName,EmptyParam,EmptyParam,EmptyParam)); // открываем нашу таблицу
MyTable.MoveFirst; // идем на первую запись так как иногда наблюдается открытие таблице с курсором не на первой строке
if MyTable.Fields['Files'].type_=dbAttachment then // проверяем тип поля, чтоб не делать лишних движений
begin
att := Recordset2(TVarData(MyTable.Fields[1].Value).VDispatch); открываем наше поле как вложенную таблицу типа Recordset2
att.MoveFirst;
while not att.EOF do
begin
ListBox1.Items.Add(att.Fields['FileName'].Value); //здесь читаем имена вложенных файлов для отображения, внимание имя поля здесь статичное.
att.MoveNext;
end;
end;
except
on E: Exception do
begin
ShowMessage(e.message);
end;
end;
end;
В результате у нас есть подключенная таблица приложений, дальше у нас есть несколько вариантов действий:
- Сохранить файл из списка вложенных файлов
- Заменить файл в списке
- Добавить файл в списке
- Удалить файл
Итак начнем по-порядку:
Сохраняем файл
procedure TForm1.SaveFile(Filename:string);
begin
att.MoveFirst;
while not att.EOF do
begin
if att.Fields['FileName'].Value=Filename then //перебираем строки в таблице вложений, пока не найдем наш файл, берем его из поля FileData в виде Field2 и сохраняем на диск
begin
(att.Fields['FileData'] as Field2).savetofile('c:\'+filename);
break;
end
else
att.MoveNext;
end;
end;
Добавляем файл
procedure TForm1.Button2Click(Sender: TObject);
var
atField:Field2;
begin
if addDialog.Execute then // диалог куда сохранять
begin
MyTable.Edit; // перевод таблицы в режим редактирования обязателен
att.MoveFirst;
att.AddNew; // добавляем новый атачмент, указатель автоматически перейдет на него
atField := Field2(att.Fields['FileData']); // получаем указатель на поле данных файла
atField.LoadFromFile(addDialog.FileName); // загружаем туда файл
att.Update(dbUpdateRegular,False); // сохраняем изменения в таблице вложений
MyTable.Update(dbUpdateRegular,False);// сохраняем изменения в главной таблице
end;
end;
Удаление файла
filename:= listbox1.Items[listbox1.ItemIndex]; // имя файла который надо удалить
att.MoveFirst;
while not att.EOF do// перебираем имена пока не найдем
begin
if att.Fields['FileName'].Value=filename then
begin
att.Delete; //удаляем вложение
break;
end
else
att.MoveNext;
end;
Ну вот собственно и все, как оказалось ничего страшного.
Спасибо за внимание