Правильный экспорт из DBGrid/DataSet в файл

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Правильный экспорт из DBGrid/DataSet в файл

Сообщение wwswowsogon » 20.11.2018 23:20:26

Всем доброго времени суток!
Продолжаю разбираться с СУБД/Firebird.

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

Код, например, такой (не обращайте внимания на кривизну;)):
Код: Выделить всё
Main.SQLQuery1.First;

  for i := 1 to Main.SQLQuery1.RecordCount - 1 do
    begin
          s0 := Main.SQLQuery1.Fields.Fields[0].AsString;
          s1 := Main.SQLQuery1.Fields.Fields[1].AsString;
          s2 := Main.SQLQuery1.Fields.Fields[2].AsString;
          s3 := Main.SQLQuery1.Fields.Fields[3].AsString;
          s4 := Main.SQLQuery1.Fields.Fields[4].AsString;
          s5 := Main.SQLQuery1.Fields.Fields[5].AsString;
          s6 := Main.SQLQuery1.Fields.Fields[6].AsString;
          s := s0 + ';' + s1 + ';' + s2 + ';' + s3 + ';' + s4 + ';' + s5 + ';' + s6;
          WriteLn(CSVFile, s);
      Main.SQLQuery1.Next;
    end;


Я зашёл в тупик: экспортируется только та часть набора, которая непосредственно видна в DBGrid. Т.е. из, например, 400 записей формируются только видимые 20-30. На мой взгляд, это странно, это было бы логично, если бы я брал данные из датасета таблицы:

Код: Выделить всё
Main.DBGrid1.DataSource.DataSet.First;


и так далее. Но ведь экспорт в данном случае происходит непосредственно из датасета? Или нет?
Почему так происходит и как с эти бороться?
wwswowsogon
новенький
 
Сообщения: 62
Зарегистрирован: 23.12.2008 20:41:37

Re: Правильный экспорт из DBGrid/DataSet в файл

Сообщение sign » 21.11.2018 06:59:54

Я работаю с MySQL, но не думаю, что есть сильные отличия в нижеприведённом коде.

Код: Выделить всё
Main.SQLQuery1.First;
while not Main.SQLQuery1.EOF do begin
{ операции с данными }
  Main.SQLQuery1.Next;
end;
sign
энтузиаст
 
Сообщения: 1034
Зарегистрирован: 30.08.2009 09:20:53

Re: Правильный экспорт из DBGrid/DataSet в файл

Сообщение Снег Север » 21.11.2018 09:29:28

wwswowsogon писал(а):Но ведь экспорт в данном случае происходит непосредственно из датасета? Или нет?

Помнится, в настройках соединения или query есть что-то про выдачу данных целиком или порциями. Покопайтесь в документации. Fetch или как-то так.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 1733
Зарегистрирован: 27.11.2007 16:14:47

Re: Правильный экспорт из DBGrid/DataSet в файл

Сообщение alexs » 21.11.2018 12:17:57

wwswowsogon
При работе с наборами данных надо использовать конструкцию
Код: Выделить всё
DS.First;
while not DS.EOF do
begin
  DS.Next;
end

Гарантированно будут выбраны все данные.
Цикл for сработает только по уже отфетченным данны. А сколько их будет стянуто с сервера - зависит от конкретных компонент и сервера.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 3750
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Правильный экспорт из DBGrid/DataSet в файл

Сообщение wwswowsogon » 21.11.2018 22:08:13

Да, действительно,
Код: Выделить всё
Main.SQLQuery1.EOF


дает нужный результат. Кто бы мог подумать, что эта конструкция принципиально отличается от

Код: Выделить всё
Main.SQLQuery1.RecordCount - 1


alexs писал(а):wwswowsogon
При работе с наборами данных надо использовать конструкцию
Гарантированно будут выбраны все данные.
Цикл for сработает только по уже отфетченным данны. А сколько их будет стянуто с сервера - зависит от конкретных компонент и сервера.


-видимо, это и есть исчерпывающий ответ. :) Спасибо большущее за наводку, сам бы ещё долго втыкал, что и как происходит в SQLQuery.
Доброго здравия и всех благ!
wwswowsogon
новенький
 
Сообщения: 62
Зарегистрирован: 23.12.2008 20:41:37

Re: Правильный экспорт из DBGrid/DataSet в файл

Сообщение alexs » 22.11.2018 14:35:25

Ну можно ещё, конечно, можно вызвать перед циклом FetchAll - если он есть у компоненты. Но не все данный метод реализуют.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 3750
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Правильный экспорт из DBGrid/DataSet в файл

Сообщение Lucifer » 27.01.2019 10:00:17

Могу еще предложить выгрузку в универсальный формат SYLK.
Код: Выделить всё
function to_sylk(ADataSet: TDataSet; const SaveHeader: Boolean = True): String;
var
  iRow, iCol: Integer;
  tmpFile: String;
  mText: TStringList;
  SR: TSearchRec;
begin
//  LazGetLanguageIDs(Lang, FallbackLang);
  try
    // Сделаем попытку удаления всех ранее нагенеренных файлов
    if FindFirst(GetTempDir + '*.slk', faAnyFile, SR) = 0 then
    begin
      repeat
        DeleteFile(GetTempDir + SR.Name)
      until
        FindNext(SR) <> 0;
      FindClose(SR);
    end;
  except
    // Возможная обработка ошибок
  end;
  // Генерируем сам файл
  try
    tmpFile := GetTempDir + GUID.NewGuid.ToString(True) + '.slk';
    mText := TStringList.Create;
    mText.Clear;
    ADataSet.First;
    iRow := 0;
    iCol := 0;
    mText.Append('ID;PWXL;N;E');
    ADataSet.DisableControls;
    if SaveHeader then
      for iCol := 0 to ADataSet.FieldCount - 1 do
        mText.Append('C;Y1;X' + (iCol + 1).ToString + ';K"' + ADataSet.Fields[iCol].FieldName + '"');
    while not ADataSet.EOF do
    begin
      for iCol := 0 to ADataSet.FieldCount - 1 do
        mText.Append('C;Y' + (iRow + 2).Tostring + ';X' + (iCol + 1).ToString + ';K"' + ADataSet.Fields[iCol].AsString + '"');
      ADataSet.Next;
      Inc(iRow);
    end;
    mText.Append('E');
    mText.Text := UTF8ToCP1251(mText.Text);
    mText.SaveToFile(tmpFile);
    Result := tmpFile;
  finally
    ADataSet.EnableControls;
    mText.Free;
  end;
end;
Lucifer
новенький
 
Сообщения: 41
Зарегистрирован: 05.01.2014 21:39:03
Откуда: Новороссийск

Re: Правильный экспорт из DBGrid/DataSet в файл

Сообщение DedFrend » 30.01.2019 18:06:06

Для Lucifer
А что это за конструкция?
Lucifer писал(а):(iCol + 1).ToString
DedFrend
новенький
 
Сообщения: 21
Зарегистрирован: 25.11.2018 12:21:50

Re: Правильный экспорт из DBGrid/DataSet в файл

Сообщение Lucifer » 13.02.2019 14:09:34

DedFrend писал(а):Для Lucifer
А что это за конструкция?
Lucifer писал(а):(iCol + 1).ToString


Ну, напиши IntToStr(iCol + 1). Ровно то же самое, но я привык пользоваться ToString
Lucifer
новенький
 
Сообщения: 41
Зарегистрирован: 05.01.2014 21:39:03
Откуда: Новороссийск


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

Рейтинг@Mail.ru