const
MaxField = 255;
sf_UnKnown = 0;
sf_String = 1;
sf_Memo = 2;
var
FieldTypes: Array[0..Pred(MaxField)] of Byte; { default unknowns }
Мы должны просмотреть структуру таблицы для получения информации об типах полей:
withTTable.Create( nil) do
try
DatabaseName := ADatabase;
TableName := ATable;
Active := True;
keys := -1; { no key in table }
fori:=0 toPred(FieldDefs.Count) do
begin
ifFields[i].IsIndexField thenkeys := i;
FieldTypes[i] := sf_String; { default }
if(FieldDefs[i].FieldClass = TMemoField) then
FieldTypes[i] := sf_Memo
else
if(FieldDefs[i].FieldClass = TGraphicField) or
(FieldDefs[i].FieldClass = TBlobField) or
(FieldDefs[i].FieldClass = TBytesField) or
(FieldDefs[i].FieldClass = TVarBytesField) then
FieldTypes[i] := sf_UnKnown { ignore }
end
finally
Free
end;
После анализа полей таблицы, мы можем пройтись по всей таблице и получить значения полей. Для каждой записи в таблице мы сгенерируем HTML-страницу. Мы можем использовать имена полей как заголовки, используя тег
для ключевых полей и тег
для не ключевых полей. Код просматривает всю таблицу т преобразовывает поля в текст и выводит их в HTML-файл:
while notEof do
begin
Inc(RecNr);
System.Assign(f,FileName+'/'+PageNr(RecNr));
System.Rewrite(f);
writeln(f,'');
writeln(f,'
');
writeln(f,'
writeln(f,Format('%s %d/%d',[ATable,RecNr,RecordCount]));
writeln(f,'');
writeln(f,'
');
writeln(f,'
');
{ print fields }
fori:=0 toPred(FieldCount) do
ifFieldTypes[i] > sf_UnKnown then
begin
if(keys >= i) thenwriteln(f,'
')
elsewriteln(f,'
');
writeln(f,FieldDefs[i].Name,':');
if(keys >= i) thenwriteln(f,'
') { }
elsewriteln(f,'
'); { }
ifFieldTypes[i] = sf_Memo then
writeMemo(f,Fields[i])
elsewriteln(f,Fields[i].AsString);
if(keys = i) thenwriteln(f,'
');
end;
writeln(f,'
');
writeln(f,'
');
System.Close(f);
Next
end;
Заметим, что я использую здесь одно недокументированное свойство HTML: для окончания заголовка вы можете написать , но вы должны использовать
для разрыва строки. Таким образом, вы можете иметь заголовки, и текст, начинающийся правее и ниже заголовка. Пожалуйста, учтите, что это недокументированное свойство и вы должны заменить его раскомментировав и если вы не желаете жить на угле <���юмор>. Следующий листинг показывает как получить информацию из мемо поля базы данных и поместить его в текстовый файл. И наконец после этого мы отформатируем немного, помня что HTML игнорирует множественные переводы строки и пробелы.
procedureWriteStream( varf: Text; varStream: TMemoryStream);
const
LF = #10;
BufSize = 8192; { bigger memos are chopped off!! }
var
Buffer: Array[0..Pred(BufSize)] ofChar;
i: Integer;
begin
Stream.Seek(0,0);
ifStream.Size > 0 then
begin
Stream. Read(Buffer,Stream.Size);
fori:=0 toPred(Pred(Stream.Size)) do
begin
{ empty line converted to
break }
if(Buffer[i] = LF) and(Buffer[i+1] = LF) thenwriteln(f,'
');
{ strip multiple spaces (are ignored anyway) }
if not((Buffer[i] = ' ') and(Buffer[i+1] = ' ')) then write(f,Buffer[i]);
{ start new sentence on a new line (but only in HTML doc itself }
if(Buffer[i] = '.') and(Buffer[i+1] = ' ') thenwriteln(f)
end;
writeln(f,Buffer[Pred(Stream.Size)])
end
elsewriteln(f,' ') { empty memo }
end {WriteStream} ;
procedureWriteMemo( varf: Text; Field: TField);
varStream: TMemoryStream;
begin
Stream := TMemoryStream.Create;
(Field AS TMemoField).SaveToStream(Stream);
WriteStream(f,Stream);
Stream.Free
end{WriteMemo};
Теперь у нас есть метод преобразования записей в HTML страницы, нам также нужен путь уникальной идентификации каждой записи. Допустим, что база данных не не содержит более 100,000 записей (Если таблица содержит свыше 100,000 записей, то конвертирование их в HTML страницы наверно не очень хорошая идея), Я думаю что подойдет схема где каждая запись помещается в файл с именем "pag#####.htm", где ##### номер записи в базе данных. Для уменьшения конфликта имен, каждая таблица должна размещаться в своем собственном каталоге (например, BIOLIFE.HTM каталог для BIOLIFE.DB таблиц, так что мы будем иметь BIOLIFE.HTM/PAG00001.HTM для первой записи из BIOLIFE.DB таблицы).
Читать дальше