Уважаемые, столкнулся с такой непростой задачкой, как работа с текстовым файлом сложной структуры. Нужно считать с него коды станций, номера платежей, суммы и коды статей. И дату. Желательно в табличку запихнуть для удобства работы. Единственный вариант, который приходит в голову, это построчное считывание и анализ. Подскажите какими методами такое можно провернуть?
вариант, который приходит в голову, это построчное считывание и анализ.
Считывание - это все равно, да и вариантов не так много. Можно и построчно. А вот потом можно и порезвиться.. Например, при считывании заполняешь двумерный массив (короткие строки дополняются пробелами), то есть получаешь картинку. Потом на этой картинке распознаешь линии, и в соответствии с этим строишь таблицу. Задача не такая сложная, как может показаться, но.. Ты уверен, что в этих файлах/картинках/таблицах не будет сбоев? Например, строка со словом "ОТДЕЛЕНИЕ" не разделена на клетки и не отделена от нижней строки. Это сбой? или так и должно быть? В подобных случаях нужно предусмотреть все возможные варианты. Иначе одна неучтенная точка смажет весь результат..
Можно возразить, что такая универсальность, как распознавание _любой_ таблицы, тут не нужна; но реально это сэкономит время. Доказать это не возьмусь, но так оно обычно бывает.
--------------------
я - ветер, я северный холодный ветер я час расставанья, я год возвращенья домой
да вроде все равно в чем хранить, вопрос кто это заносит: юзер или твоя прога табличку можно по разному хранить.... а если этот файл создает твоя прога (что наверно надежней будет) то ты сам можешь закодить любой удобный те формат
если для дела лучше вобще БД использовать а если курсак ;) можно повозиться
Да файл мне прога выкидывает, но не моя и менять я в ней не могу ничего. В файле много лишнего. Мне нужна только сумма по станции и код станции с датой. все остальное игнорировать. Данные мне нужны для БД. Есть примерный вариант как анализировать подобное, а то не так долго работаю с делфи, опыт а еще пока нету.
--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
ширина стобцов меняться может? если нет то все упрощается берешь строку от сих до сих и вот те ячейка....
шапка тож наверно статична можно сразу отбросить строки придется проверять, что именно в строке берешь ищешь твою "по станции", как нашел значит все строки до следующей "по станции" твои... (ну кроме разделителей)
еще может можно ориентироваться по :---- |
для удобства грузи в Тмемо строки сразу и видеть будешь что загрузил а разносить конечно в массив или по усмотрению может сразу в твою БД как удобней
Читаешь файл в строку, и в цикле вытягиваешь из нее регулярным выражением фразу "ПО СТАНЦИИ", и следующие 2 вещественных числа. Первое будет кодом станции, второе - общая сумма.
Свободная библиотека для работы с регулярками в Дельфи лежит вот тут: TPerlRegEx
надо и так попробовать, спасибо. Дату я забрал, правда, может и не самым красивым способом. Подозреваю, что косяки еще могут меня встретить.
//чтение из файла while not EOF(f) do begin readln(f,buf); // прочитать строку из файла Memo1.Lines.Add(buf); // добавить строку в поле Memo1 if buf[27]='З' then Form4.Edit2.Text:=copy(buf,30,42); end; CloseFile(f); // закрыть файл begin Form4.ComboBox1.Text:=mounth; Form4.Edit3.Text:=god; data1:=mounth + ' ' + god; Form4.Edit3.text:=data2;
Клевый код, очень быстро работает. Вот с датой проще, наверное до 6 строки пролистать. а чтобы символы "Г."отбросить просто отминусовать их от конца или есть проще варианты? Еще проблема возникла в том, что версия проги выбрасывающая отчет сменилась, и изменился отчетный файлик. В нем три вида отчетов, мне нужны станции с кодами платежей и цифрами по ним по ФО-7л и ФО-7н, Фо-7М не нужно. Возникла идея разбить на два текстовика с нужным содержим по Фо-7л и Н, а как можно определять начало и концовки их?
Решил просто перебирать тупо строки и писать в StringGrid. По задумке должно было писать все строки начинающиеся с символа "|", но чет не очень вышло, пишет только три первых столбца и заполняет чушью.
procedure TForm4.Button5Click(Sender: TObject); var F:TextFile; //файл fName: String[100]; // имя файла buf: String[80]; //буфер для чтения строк i:integer; //шагалка stroka:string; //строка year,mounth:string; //месяц и год введение пользователем data1,data2:string; //дата считываемая и отображаемая
begin fName:=Form4.Edit1.Text; //забираем путь AssignFile(f,fName); // try Reset(F); // открыть для чтения except on EInOutError do begin ShowMessage('Ошибка доступа к файлу'+fName); exit; end end;
while not EOF(f) do begin for i := 0 to StringGrid1.RowCount - 1 do begin Form4.StringGrid1.Cells[0,i]:=copy(buf,9,16); (имя) Form4.StringGrid1.Cells[1,i]:=copy(buf,21,27);(код) Form4.StringGrid1.Cells[2,i]:=copy(buf,27,106);(код) Form4.StringGrid1.Cells[3,i]:=copy(buf,107,120);(сумма) Form4.StringGrid1.Cells[4,i]:=copy(buf,122,127);(статья) //чтение из файла
begin readln(f,buf); // прочитать строку из файла if buf[1]='|' then end; end; if buf[27]='З' then begin Form4.Edit2.Text:=copy(buf,30,42); //забрал дату end; end; CloseFile(f); // закрыть файл
begin Form4.ComboBox1.Text:=mounth; Form4.Edit3.Text:=year; data1:=mounth + ' ' + year; Form4.Edit3.text:=data2;
Вроде разобрался с заполнение, только из пяти столбцов заполняются только первые три. В чем причина не пойму. Как можно удалить строки из грида, если там пустые ячейки или не нужные мне значения? И кучнеи сбить, а то пробелов с пустыми строками полно.
--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
procedure TForm4.Button5Click(Sender: TObject); var F:TextFile; //файл fName: String[100]; // имя файла buf: String[127]; //буфер для чтения строк i:integer; //шагалка stroka:string; //строка year,mounth:string; //месяц и год введение пользователем data1,data2:string; //дата считываемая и отображаемая name_stat:string;
{ begin if Form4.Edit3.Text=null then ShowMessage('Не указан год загрузки!!!'); exit; if Form4.ComboBox1.Text=null then ShowMessage('Не выбран месяц загрузки'); exit; }
begin fName:=Form4.Edit1.Text; //забираем путь AssignFile(f,fName); try Reset(F); // открыть для чтения except on EInOutError do begin ShowMessage('Ошибка доступа к файлу'+fName); exit; end end; i:=1; while not EOF(f) do
begin readln(f,buf); // прочитать строку из файла // длина строки в образце фиксированная.
if buf[27]='З' then Form4.Edit2.Text:=copy(buf,30,20);
if POS(':',buf[1])>0 then continue else begin if POS('(',buf[1])>0 then continue else begin if POS(' ',buf[1])>0 then continue;
if buf[1]='|' then begin if POS('ЕЛЕНИЕ',buf)>0 then continue else begin if POS('СТАНЦИИ',buf)>0 then continue else begin if POS('ГО ПО ОТДЕ',buf)>0 then continue else begin if POS('ГО ПО ДОРО',buf)>0 then continue else begin Form4.StringGrid1.Cells[0,i]:=copy(buf,7,10); Form4.StringGrid1.Cells[1,i]:=copy(buf,20,3); Form4.StringGrid1.Cells[2,i]:=copy(buf,26,79); Form4.StringGrid1.Cells[3,i]:=copy(buf,106,13); Form4.StringGrid1.Cells[4,i]:=copy(buf,121,4); if Form4.StringGrid1.Cells[0,i]<>' ' then name_stat:=Form4.StringGrid1.Cells[0,i]; if Form4.StringGrid1.Cells[0,i]=' ' then Form4.StringGrid1.Cells[0,i]:=name_stat; inc(i); end; end; end; end; end; end; end; end;
CloseFile(f); // закрыть файл
begin mounth:=Form4.ComboBox1.Text; //месяц клиента year:=Form4.Edit3.Text; // год клиента data1:=mounth + ' ' + year + ' Г.';// дата клиента data2:=Form4.Edit2.Text; // дата из файла Form4.Edit4.Text:=data1; if data1<>data2 then begin ShowMessage('Дата загрузки не соответствует указанной дате'); Form4.Button6.Enabled:=False; end; if data1=data2 then begin ShowMessage('Дата ввода корректна'); Form4.Button6.Enabled:=True; Form4.ComboBox1.Enabled:=False; Form4.Edit3.Enabled:=False; end;
for i := 1 to StringGrid1.RowCount - 1 do begin if Form4.StringGrid1.Cells[1,i]<>'147' then if Form4.StringGrid1.Cells[1,i]<>'163' then if Form4.StringGrid1.Cells[1,i]<>'143' then if Form4.StringGrid1.Cells[1,i]<>'150' then if Form4.StringGrid1.Cells[1,i]<>'166' then if Form4.StringGrid1.Cells[1,i]<>'149' then if Form4.StringGrid1.Cells[1,i]<>'154' then if Form4.StringGrid1.Cells[1,i]<>'144' then if Form4.StringGrid1.Cells[1,i]<>'145' then if Form4.StringGrid1.Cells[1,i]<>'169' then if Form4.StringGrid1.Cells[1,i]<>'158' then if Form4.StringGrid1.Cells[1,i]<>'161' then if Form4.StringGrid1.Cells[1,i]<>'151' then if Form4.StringGrid1.Cells[1,i]<>'162' then if Form4.StringGrid1.Cells[1,i]<>'171' then if Form4.StringGrid1.Cells[1,i]<>'124' then if Form4.StringGrid1.Cells[1,i]<>'160' then
begin Form4.StringGrid2.Cells[0,i]:=Form4.StringGrid1.Cells[0,i]; Form4.StringGrid2.Cells[1,i]:=Form4.StringGrid1.Cells[1,i]; Form4.StringGrid2.Cells[2,i]:=Form4.StringGrid1.Cells[2,i]; Form4.StringGrid2.Cells[3,i]:=Form4.StringGrid1.Cells[3,i]; Form4.StringGrid2.Cells[4,i]:=Form4.StringGrid1.Cells[4,i];
begin if Form4.StringGrid2.Cells[0,i]<>' ' then name_stat:=Form4.StringGrid2.Cells[0,i]; if Form4.StringGrid2.Cells[0,i]=' ' then Form4.StringGrid2.Cells[0,i]:=name_stat;
{ if Form4.StringGrid1.Cells[0,i]<>' ' then name_stat:=Form4.StringGrid1.Cells[0,i]; if Form4.StringGrid1.Cells[0,i]=' ' then Form4.StringGrid1.Cells[0,i]:=name_stat; } end; end; end;
end; end;
Один вопрос, как маску наложить на Едит в 4 символа цифровых. И организовать его проверку на корректный ввод?
Еще один маленький вопросик. Надо в табличку положить коды станций, но чет они у меня не хотят вставать как нужно и "размножаться". И еще как заставить стринггрид заполняться строка в соответствии с записями, а то я руками вбухал 200, что не есть хорошо. Во второй грид гружу по выборке.
procedure TForm4.Button5Click(Sender: TObject); var F:TextFile; //файл fName: String[100]; // имя файла buf: String[127]; //буфер для чтения строк i:integer; //шагалка stroka:string; //строка year,mounth:string; //месяц и год введение пользователем data1,data2:string; //дата считываемая и отображаемая name_stat:string; kod_stat:string; j:integer; kod_plateg:string; // код платежа
Kod_state:string; { begin if Form4.Edit3.Text=null then ShowMessage('Не указан год загрузки!!!'); exit; if Form4.ComboBox1.Text=null then ShowMessage('Не выбран месяц загрузки'); exit; }
begin
fName:=Form4.Edit1.Text; //забираем путь AssignFile(f,fName); try Reset(F); // открыть для чтения except on EInOutError do begin ShowMessage('Ошибка доступа к файлу'+fName); exit; end end; i:=1; j:=1; while not EOF(f) do
begin readln(f,buf); // прочитать строку из файла // длина строки в образце фиксированная.
if buf[27]='З' then Form4.Edit2.Text:=copy(buf,30,20);
if POS(':',buf[1])>0 then continue else begin if POS('(',buf[1])>0 then continue else begin if POS(' ',buf[1])>0 then continue;
if buf[1]='|' then begin if POS('ЕЛЕНИЕ',buf)>0 then continue else begin if POS('ПО СТАНЦИИ',buf)>0 then Form4.StringGrid1.Cells[5,j]:=copy(buf,17,7); if POS('СТАНЦИИ',buf)>0 then continue else begin if POS('ГО ПО ОТДЕ',buf)>0 then continue else begin if POS('ГО ПО ДОРО',buf)>0 then continue else begin Form4.StringGrid1.Cells[0,i]:=copy(buf,7,10); Form4.StringGrid1.Cells[1,i]:=copy(buf,20,3); Form4.StringGrid1.Cells[2,i]:=copy(buf,26,79); Form4.StringGrid1.Cells[3,i]:=copy(buf,106,13); Form4.StringGrid1.Cells[4,i]:=copy(buf,121,4);
if Form4.StringGrid1.Cells[0,i]<>' ' then name_stat:=Form4.StringGrid1.Cells[0,i];
if Form4.StringGrid1.Cells[0,i]=' ' then Form4.StringGrid1.Cells[0,i]:=name_stat;
if Form4.StringGrid1.Cells[5,i]<>'123' then Kod_stat:= Form4.StringGrid1.Cells[5,i]; // это я тут пытался присвоить имена if Form4.StringGrid1.Cells[5,i]='' then Form4.StringGrid1.Cells[5,i]:=Kod_stat; inc(j); inc(i); end; end; end; end; end; end; end; end;
CloseFile(f); // закрыть файл
begin mounth:=Form4.ComboBox1.Text; //месяц клиента year:=Form4.Edit3.Text; // год клиента data1:=mounth + ' ' + year + ' Г.';// дата клиента data2:=Form4.Edit2.Text; // дата из файла Form4.Edit4.Text:=data1; if data1<>data2 then begin ShowMessage('Дата загрузки не соответствует указанной дате'); Form4.Button6.Enabled:=False; end; if data1=data2 then begin ShowMessage('Дата ввода корректна'); Form4.Button6.Enabled:=True; Form4.ComboBox1.Enabled:=False; Form4.Edit3.Enabled:=False; end;
Form4.SocketConnection1.Connected:=false; Form4.SocketConnection1.Connected:=true; Form4.SocketConnection1.AppServer.openbase('ORA8','fs_master','fs'); kod_plateg:='select KOD_PLATEG_FO7 from SPR_PLATEG_FO7'; kod_state:='select KODEXP7 from SPR_MSTO where KODEXP <> 0 '; Form4.ClientDataSet1.close;
Form4.ClientDataSet1.DataRequest(kod_plateg); Form4.ClientDataSet1.open; // Form4.ClientDataSet1.DataRequest(kod_state); // Form4.ClientDataSet1.open; while not Form4.ClientDataSet1.eof do begin
for i := 1 to StringGrid1.RowCount - 1 do begin kod_plateg:=Form4.ClientDataSet1.fieldbyname('KOD_PLATEG_FO7').asstring; // kod_state:=Form4.ClientDataSet1.fieldbyname('KODEXP7').asstring;
if Form4.StringGrid1.Cells[1,i]= kod_plateg then //выборка нужных платежей begin Form4.StringGrid2.Cells[0,i]:=Form4.StringGrid1.Cells[0,i]; Form4.StringGrid2.Cells[1,i]:=Form4.StringGrid1.Cells[1,i]; Form4.StringGrid2.Cells[2,i]:=Form4.StringGrid1.Cells[2,i]; Form4.StringGrid2.Cells[3,i]:=Form4.StringGrid1.Cells[3,i]; Form4.StringGrid2.Cells[4,i]:=Form4.StringGrid1.Cells[4,i]; Form4.StringGrid2.Cells[5,i]:=Form4.StringGrid1.Cells[5,i];