Страница 1 из 1

Класс для работы с csv

Добавлено: 03 Август 2017, 15:09
finsoftrz
Привет всем. Сегодня с утра сделал небольшой класс для обмена через csv файлы. Выкладываю, возможно, кому пригодится.
Решил систематизировать функции обмена своей учетной системы. Это может быть обмен между копиями своей программы или обмен с другими внешними программами. Сейчас уже набралась кучка разных обработок.
Вначале думал делать все через xml, благо такой инструмент уже давно был разработан. Но разница в размере файлов и скорости их обработки все же весьма значительна (в районе 10 раз в пользу csv). Поэтому решил, что пусть будут оба варианта, а применять можно по обстоятельствам.
Основные задачи - минимизировать код в приложении и сделать развязку по составу и очередности следования полей между отправляющей и принимающей стороной.
Пример кода отправителя.

Код: Выделить всё

send_r  routine
   DATA
lor:queue  queue, pre()
lor:name  string(40), name('name')
lor:kol   long, name('kol')
.

lor:queue2  queue, pre()
lor:name2  string(40), name('name')
.

lor:fsCSV  &fsCSV
   CODE

   lor:name='Тестовое "1" значение'
   lor:kol=1
   add(lor:queue)

   lor:name='Тестовое значение 2' & CHR(13) & CHR(10) & 'вторая строка'
   lor:kol=2
   add(lor:queue)

   lor:name='Тестовое значение 3'
   lor:kol=3
   add(lor:queue)

   lor:name2='Вторая очередь'
   add(lor:queue2)

   lor:fsCSV  &= new(fsCSV)
   lor:fsCSV.init

   lor:fsCSV.SetStruct('queue',lor:queue)
   lor:fsCSV.SetStruct('queue2',lor:queue2)
   lor:fsCSV.ExportQueue('queue',lor:queue)
   lor:fsCSV.ExportQueue('queue2',lor:queue2)

   lor:fsCSV.MakeFile('1.csv')

   lor:fsCSV.kill
   dispose(lor:fsCSV)

   free(lor:queue)

   run('notepad.exe 1.csv')
Получаемый в результате файл выглядит так.
#queue,name,kol
#queue2,name
queue,"Тестовое ""1"" значение","1"
queue,"Тестовое значение 2@`3@`0вторая строка","2"
queue,"Тестовое значение 3","3"
queue2,"Вторая очередь"

Вначале выводится описание структур, затем следуют записи каждой структуры. Кавычки внутри строк автоматически удваиваются, символы перевода строки заменяются специальными последовательностями (при приеме исходный вид восстанавливается). Кроме метода ExportQueue, который выгружает очередь, можно использовать метод ExportGroup. В этом случае мы также объявляем очередь, но не заполняем ее, а просто присваиваем значения полям, а затем экспортируем по одной записи. Например, через next читаем таблицу базы, присваиваем нужные поля в структуре queue (в том числе через :=:) и экспортируем методом ExportGroup.

На принимающей стороне код выглядит следующим образом.

Код: Выделить всё

recive_r  routine
   DATA
lor:queue  queue, pre()
lor:kol   long, name('kol')
lor:name  string(40), name('name')
.

lor:queue2  queue, pre()
lor:name2  string(40), name('name')
.

lor:fsCSV  &fsCSV
   CODE

   lor:fsCSV  &= new(fsCSV)
   lor:fsCSV.init

   lor:fsCSV.SetStruct('queue',lor:queue)
   lor:fsCSV.SetStruct('queue2',lor:queue2)
   lor:fsCSV.ImportFile('1.csv',0)

   lor:fsCSV.kill
   dispose(lor:fsCSV)

   !здесь свой код для проверки содержимого очередей
   !fsViewQueue('',lor:queue)
   !fsViewQueue('',lor:queue2)

   free(lor:queue)
   free(lor:queue2)
В этом примере в первой очереди специально изменен порядок полей, чтобы показать независимость их следования. Метод ImportFile автоматически загружает из csv все продекларированные очереди. Кроме него можно использовать метод ImportRec для построчной обработки. В этом случае вначале вызываем ImportFile с 1 во втором параметре, в результате сопоставляются структуры отправителя и приемника без загрузки данных. Затем читаем построчно csv через ascii драйвер и вызываем ImportRec с параметром в виде строки исходного файла. Метод загружает поля какой-то из структур и возвращает имя структуры. Может быть полезно при разборе больших файлов, чтобы не загружать все предварительно в кьюшки.