Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?

Официальный форум Simple-Scada.

Автор Тема: Работа с CSV файлами  (Прочитано 4320 раз)

Павло

  • Новичок
  • *
  • Сообщений: 31
  • Павло Кулініч
    • Просмотр профиля
    • Simple-Scada Україна
Работа с CSV файлами
« : 24 Июля 2020, 15:11:54 »
Добрьій день.

В руководстве по скриптах есть пример работьі с CSV через процедуру.
Код: (delphi)
{ вспомогательная процедура для обработки отдельной строки }
  procedure ProcStr(const AStr: string);
  var
    I: Integer;
    aBuf: string;
 
    { эта подпроцедура вызывается каждый раз когда из строки было извлечено
      значение отделённое ";" }
    procedure OnDone;
    begin
      if aBuf = '' then Exit;  // игнорируем пустые значения
      // ...
      // здесь работаем с полученным значением, которое хранится в aBuf
      // ...
      aBuf := '';  // затем обнуляем буферную строку
    end;
  begin
    aBuf := '';
    for I := 1 to Length(AStr) do   // проходим по каждому символу строки в цикле
      if aStr[I] <> ';' then        // если текущий символ не ";", то
      begin
        if aStr[I] <> ' ' then      // игнорируем пробелы
          aBuf := aBuf + AStr[I]    // добавляем символ в буферную строку
      end else                      // если дошли до ";", то
        OnDone;                     // работаем с полученным значением
 
    OnDone;  // вызываем завершающую процедуру напоследок
  end;         
 
begin
  // открываем текстовый файл для чтения
  if TextFileOpen('MyCSV.csv', 'D:\', fomReset, fcpDefault) then
  begin
    while not TextFileEOF do     // цикл с проходом по каждой строке текстового файла
      ProcStr(TextFileReadLn);   // считываем и обрабатываем очередную строку
 
    TextFileClose;               // закрываем файл
  end;
end.
В месте "здесь работаем с полученным значением, которое хранится в aBuf" - можно показать пример?  :D
« Изменён: 28 Июля 2020, 13:18:34 от Simple-Scada »

Simple_Scada

  • Администратор
  • *****
  • Сообщений: 1407
    • Просмотр профиля
Re: Работа с CSV файлами
« Ответ #1 : 28 Июля 2020, 11:54:58 »
Здравствуйте.

Цитировать
В месте "здесь работаем с полученным значением, которое хранится в aBuf" - можно показать пример?
Все зависит от того, что требуется сделать с полученными из файла данными, например можно вывести их в объект "Текст" или записывать полученные значения в переменные и т.д, например:
Код: (delphi)
procedure OnDone;
    var
      aVar: TM_Variable;
    begin
      if aBuf = '' then Exit;  // игнорируем пустые значения

      Text1.Text := Text1.Text + ' ' + aBuf; // записываем значения из CSV-файла в текст

      { записываем значения в переменные vrCSV_0, vrCSV_1, vrCSV_2 .... }
      aVar := GetVariableByName('vrCSV_' + IntToStr(vrCSV_Counter.AsInt));
      if aVar <> nil then aVar.Value := StrToFloat(aBuf);

      vrCSV_Counter.Value := vrCSV_Counter.Value + 1;
      aBuf := '';  // затем обнуляем буферную строку
    end;
   

pan2000

  • Постоялец
  • ***
  • Сообщений: 226
    • Просмотр профиля
Re: Работа с CSV файлами
« Ответ #2 : 28 Июля 2020, 15:20:38 »
          Здравствуйте!

К сожалению, { вспомогательная процедура для обработки отдельной строки } не сможет правильно разобрать строку из CSV-файла экспорта переменных, содержащую пустые поля (и "пробелы").
Для разбора CSV-строки можно использовать функции из примера заполнения таблиц описанием переменных из CSV-файла:
Код: (delphi)
// выбор поля по индексу (произвольный выбор)
function GetField(const aStr: string; const n: integer): string;
var i, j: integer;
    aStr1: string;
begin
  j := 1; aStr1 := '';
  for i := 1 to Length(aStr) do begin
    if aStr[i] = ';' then begin
      if j = n then begin GetField := aStr1; exit; end;  // индекс выбора поля равен номеру выбранного поля
      aStr1 := '';                                       // новое поле
      j := j + 1;
    end
    else aStr1 := aStr1 + Astr[i];
  end;
  GetField := aStr1;     // пусто или последнее поле с отсутствующим разделителем ";"
end;

// последовательный выбор полей
function GetField2(const aStr: string; var n: integer): string;
var i: integer;
    aStr1: string;
begin
  aStr1 := '';
  for i := n to Length(aStr) do
    if aStr[i] = ';' then begin
      n := i + 1;                      // запомнить начало следующего поля
      GetField2 := aStr1;
      exit;
    end
    else aStr1 := aStr1 + Astr[i];
  GetField2 := aStr1;
end;

var aStr: string;
    i, j, k: integer;
begin
// открываем текстовый файл для чтения
 if TextFileOpen('MyCSV.csv', '', fomReset, fcpDefault) then begin
    TextFileReadLn;                                          // пропустить первую строку
    i := 0;
    with Table1 do
      while (not TextFileEOF) and (i < RowCount) do begin    // цикл с проходом по каждой строке текстового файла или до переполнения таблицы
        aStr := TextFileReadLn;
// функция GetField()
        for j := 1 to ColumnsCount do GetCell(j - 1, i).Text := GetField(aStr, j);

        for j := 0 to 3 do                // заполнение Table3 выбранными столбцами
          case j of
          0: Table3.GetCell(j, i).Text := GetField(aStr, 2);    // Имя переменной
          1: Table3.GetCell(j, i).Text := GetField(aStr, 3);    // Тип данных
          2: Table3.GetCell(j, i).Text := GetField(aStr, 8);    // Начальное значение
          3: Table3.GetCell(j, i).Text := GetField(aStr, 32);   // ID
          end;
// функция GetField2() - заполнение таблицы Table2 идентичной таблице Table1
        k := 1;     // индекс начала очередного поля в строке разбора aStr
        for j := 1 to ColumnsCount do Table2.GetCell(j - 1, i).Text := GetField2(aStr, k);

        i := i + 1;
      end;
    TextFileClose;
  end;
end.