unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, StrUtils, DateUtils, ComCtrls, ExtCtrls, ToolWin;
type
TForm1 = class(TForm)
Go_Button: TButton;
OpenDialog1: TOpenDialog;
OpenButton: TButton;
SaveDialog1: TSaveDialog;
BtnRe: TButton;
ToolBar1: TToolBar;
Panel1: TPanel;
StatusBar1: TStatusBar;
ProgressBar1: TProgressBar;
SrcOpenDialog: TOpenDialog;
MProtocol: TRichEdit;
procedure FormCreate(Sender: TObject);
procedure BtnReClick(Sender: TObject);
procedure OpenButtonClick(Sender: TObject);
procedure Go_ButtonClick(Sender: TObject);
function ToOEM(S:String):String;
function ToAnsi(S:String):String;
function WriteLog(Level:Integer; S:String):String;
function FileSizeByName(Name:String): Integer;
function isNum(const st:string): boolean;
private
{ Private declarations }
public
{ Public declarations }
end;
const
OstPref='BOS1_';
OstSrcPref='RBN';
OperPref='BV100_';
OperSrcPref='ZNO';
NalschPref='BNS1_';
NalschSrcPref='ZNO';
ReceiptPref='PB1_';
ChunkLimit=470000; //524288 - 512К
Bic='10813823';
INN='7744001497';
ERR=0;
WARN=1;
INFO=2;
var
Form1: TForm1;
InFile,OutFile: TextFile;
CurrentFileNum,NumOutFiles,OutFileSize: Integer;
SIn,SOut: String;
InFileSize, InFilePosition: Integer;
DateZapr,KodNO,NomZapr,NomResh,DateResh :String;
NumericTags: TStringList;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
DateZapr:='';
NomZapr:='';
NomResh:='';
DateResh:='';
NumericTags := TStringList.Create;
NumericTags.Add('ИННКО');
NumericTags.Add('КППКО');
NumericTags.Add('БИК');
NumericTags.Add('ИНННП');
NumericTags.Add('КППНП');
NumericTags.Add('НомСчПП');
NumericTags.Add('НомСч');
NumericTags.Add('БИКБП');
NumericTags.Add('НомКоррСч');
NumericTags.Add('НомДок');
NumericTags.Sort; //for Find method!
end;
procedure TForm1.OpenButtonClick(Sender: TObject);
begin
OpenDialog1.execute;
DateZapr:='';
NomZapr:='';
NomResh:='';
DateResh:='';
MProtocol.Text:='';
WriteLog(INFO,'Файл к обработке: '+OpenDialog1.Filename+''#13+#10);
end;
procedure TForm1.BtnReClick(Sender: TObject);
var
FileName,DateStr: String;
NameLength: Integer;
Today: TDateTime;
begin
//Формирование подтерждения по заданному файлу
//ZNO10813823_774820120203_000594###
//10@@@
//2012-02-06@@@
//10:35:37@@@
//===
if (AnsiPos('.',ExtractFileName(OpenDialog1.FileName))<>0) then
SaveDialog1.FileName:=ReceiptPref+MidStr(ExtractFileName(OpenDialog1.FileName),1,AnsiPos('.',ExtractFileName(OpenDialog1.FileName))-1)+'.TXT'
else
SaveDialog1.FileName:=ReceiptPref+ExtractFileName(OpenDialog1.FileName)+'.TXT';
SaveDialog1.Execute;
WriteLog(INFO,'Имя файла подтверждения: '+SaveDialog1.FileName+''#13+#10);
Rewrite(OutFile,SaveDialog1.FileName);
FileName:=ExtractFileName(OpenDialog1.FileName);
Writelog(INFO,''#13+#10); // empty line before receipt
Write(OutFile,MidStr(FileName,1,Length(FileName)-4)+'###'+''#13+#10);
WriteLog(INFO,MidStr(FileName,1,Length(FileName)-4)+'###'+''#13+#10);
Write(OutFile,'10@@@'+''#13+#10);
Writelog(INFO,'10@@@'+''#13+#10);
DateStr:=DateToStr(Now);
Write(OutFile,MidStr(DateStr,7,4)+'-'+MidStr(DateStr,4,2)+'-'+MidStr(DateStr,1,2)+'@@@'+''#13+#10);
Writelog(INFO,MidStr(DateStr,7,4)+'-'+MidStr(DateStr,4,2)+'-'+MidStr(DateStr,1,2)+'@@@'+''#13+#10);
Write(OutFile,TimeToStr(Now)+'@@@'+''#13+#10);
Writelog(INFO,TimeToStr(Now)+'@@@'+''#13+#10);
Write(OutFile,'==='+''#13+#10);
Writelog(INFO,'==='+''#13+#10);
Flush(OutFile);
CloseFile(OutFile);
end;
procedure TForm1.Go_ButtonClick(Sender: TObject);
var
Id: TGUID;
StringNo, StringCount,Code: Integer;
Tag,Val,HeaderTag,HeaderVal,StrNo,StrFileNo,StrNumOutFiles,DateForName,NomForName, InfType, Pref: String;
TagLength,HeaderTagLength,i: Integer;
RetCode:Boolean;
TopHeader,ThirdHeader: Array of String;
TopHeaderLength,ThirdHeaderLength,HeaderState: Integer;
Index: Integer;
begin
CurrentFileNum:=1;
OutFileSize:=0;
InFilePosition:=0;
MProtocol.Text:='';
WriteLog(INFO,'Файл к обработке: '+OpenDialog1.Filename+''#13+#10);
if not (FileExists(OpenDialog1.Filename)) then exit;
InFileSize:=FileSizeByName(OpenDialog1.Filename);
ProgressBar1.Min:=0;
ProgressBar1.Max:=InFileSize;
ProgressBar1.Position:=0;
AssignFile(InFile,OpenDialog1.Filename);
// Rewrite(OutFile, OpenDialog1.Filename+'.chk1');
Rewrite(OutFile, OpenDialog1.Filename+'.chk'+Format('%.2d',[CurrentFileNum]));
Reset(InFile);
if InFileSize > ChunkLimit then
begin
WriteLog(WARN,'Размер файла больше предельного размера одной части'#13+#10);
NumOutFiles:=(InFileSize div ChunkLimit)+1;
Str(NumOutFiles,StrNumOutFiles);
end;
HeaderState:=0;
TopHeaderLength:=0;
ThirdHeaderLength:=0;
while not Eof(InFile) do
begin
Readln(InFile, SIn);
SOut:=ToAnsi(SIn);
if HeaderState < 3 then //Еще не считали все заголовки
begin
if HeaderState=0 then
begin //read top header
TopHeaderLength:=TopHeaderLength+1;
SetLength(TopHeader,TopHeaderLength);
TopHeader[TopHeaderLength-1]:=SOut;
end;
if HeaderState=2 then
begin //read 3rd header
ThirdHeaderLength:=ThirdHeaderLength+1;
SetLength(ThirdHeader,ThirdHeaderLength);
ThirdHeader[ThirdHeaderLength-1]:=SOut;
end;
if SOut='###' then HeaderState:=HeaderState+1;
end;
StringNo:=StringNo+1;
Str(StringNo,StrNo);
TagLength:=AnsiPos(':',SOut)-1;
if TagLength<>-1 then
begin
Tag:=MidStr(SOut,1,TagLength);
Val:=MidStr(SOut,TagLength+2,Length(SOut)-TagLength-1);
if (Tag = 'НомСч') and (HeaderState >=3) then // found new 3rd header when already read top 3 headers
begin
HeaderState:=2; //return to 3rd header mode
ThirdHeaderLength:=1; //set 1st line of 3rd header
ThirdHeader[ThirdHeaderLength-1]:=SOut; // write it down
WriteLog(INFO,'Строка '+StrNo+' - Найдено:'+SOut);
end;
if Tag = 'ТипИнф' then
begin
InfType:=Val;
WriteLog(INFO,'Строка '+StrNo+' - Найден ТипИнф:'+InfType);
end;
if Tag = 'ИдФайл' then
begin
CreateGUID(Id);
SOut:='ИдФайл:'+ Val + MidStr(GUIDToString(Id),2,36);
WriteLog(INFO,'Строка '+StrNo+' - Добавлен GUID к ИдФайл');
end;
if Tag = 'КодНО' then
begin
KodNO:=Val;
WriteLog(INFO,'Строка '+StrNo+' - Найден КодНО:'+KodNO);
end;
if Tag = 'ИдДок' then
begin
CreateGUID(Id);
SOut:='ИдДок:'+ MidStr(GUIDToString(Id),2,36);
WriteLog(INFO,'Строка '+StrNo+' - добавлен GUID к ИдДок');
end;
if (Tag = 'НомЧасти') and (InFileSize <= ChunkLimit) then
begin
SOut:='';
WriteLog(INFO,'Строка '+StrNo+' - Удален НомЧасти');
end;
if (Tag = 'КолДок') and (InFileSize > ChunkLimit) then
begin
SOut:='КолДок:'+StrNumOutFiles;
WriteLog(INFO,'Строка '+StrNo+' - КолДок исправлен');
end;
if Tag = 'НомЗапр' then
begin
NomZapr:='';
for i := length(Val) to 6 - 1 do NomZapr:=NomZapr+'0';
NomZapr:=NomZapr+Val;
WriteLog(INFO,'Строка '+StrNo+' - Найден НомЗапр:'+NomZapr);
end;
if Tag = 'ДатаЗапр' then
begin
DateZapr:=MidStr(Val,7,4)+MidStr(Val,4,2)+MidStr(Val,1,2);
WriteLog(INFO,'Строка '+StrNo+' - Найдена ДатаЗапр:'+DateZapr);
end;
if Tag = 'НомРеш' then
begin
NomResh:='';
for i := length(Val) to 6 - 1 do NomResh:=NomResh+'0';
NomResh:=NomResh+Val;
WriteLog(INFO,'Строка '+StrNo+' - Найден НомРеш:'+NomResh);
end;
if Tag = 'ДатаРеш' then
begin
DateResh:=MidStr(Val,7,4)+MidStr(Val,4,2)+MidStr(Val,1,2);
WriteLog(INFO,'Строка '+StrNo+' - Найдена ДатаРеш:'+DateResh);
end;
if (NumericTags.Find(Tag,index)) then // Проверка корректности значений числовых тегов
begin
if not isNum(Val) then
WriteLog(ERR,'Строка '+StrNo+' - Ошибка: Не числовые значения:'+Tag+':'+Val);
end;
if (Val='') and (Tag<>'ИдДок') then // Только последним, после обработки других
begin
WriteLog(WARN,'Строка '+StrNo+' - Обнаружен пустой тег:'+Tag);
end;
end
else //No tags found!
begin
if (AnsiPos('Ошибка',SOut))<>0 then
begin
WriteLog(ERR,'Строка '+StrNo+' - Найдена ошибка: '+SOut);
end;
if (AnsiPos('Ожидается',SOut))<>0 then
begin
WriteLog(ERR,'Строка '+StrNo+' - Найдена ошибка: '+SOut);
end;
end;
if SOut<>'' then
begin
Writeln(OutFile,ToOEM(SOut));
OutFileSize:=OutFileSize+Length(SOut);
InFilePosition:=InFilePosition+Length(SOut);
ProgressBar1.Position:=InFilePosition;
if (OutFileSize > ChunkLimit) and (TagLength =-1) then
//достигли предела и не в середине документа
begin
Writeln(OutFile,'@@@');
Writeln(OutFile,'===');
OutFileSize:=0;
Flush(OutFile);
CloseFile(OutFile);
CurrentFileNum:=CurrentFileNum+1;
StrFileNo:=Format('%.2d',[CurrentFileNum]); // for filename - with leading zero's
WriteLog(INFO,'Строка '+StrNo+' - Начало части '+StrFileNo);
Rewrite(OutFile, OpenDialog1.Filename+'.chk'+StrFileNo);
Str(CurrentFileNum,StrFileNo); // for tag in the file - without leading zeros
for i:=0 to TopHeaderLength - 1 do
begin
HeaderTagLength:=AnsiPos(':',TopHeader[i])-1;
HeaderTag:=MidStr(TopHeader[i],1,HeaderTagLength);
HeaderVal:=MidStr(TopHeader[i],HeaderTagLength+2,Length(TopHeader[i])-HeaderTagLength-1);
if HeaderTag='ИдФайл' then
TopHeader[i]:='ИдФайл:'+ MidStr(HeaderVal,1,29) + MidStr(GUIDToString(Id),2,36);
if HeaderTag='НомЧасти' then
TopHeader[i]:='НомЧасти:'+ StrFileNo;
if HeaderTag='КолДок' then
TopHeader[i]:='КолДок:'+ StrNumOutFiles;
Writeln(OutFile,ToOEM(TopHeader[i]));
end;
Writeln(OutFile,ToOEM('@@@')); // добавить недостающие собаки после первого заголовка
for i:=0 to ThirdHeaderLength - 1 do
Writeln(OutFile,ToOEM(ThirdHeader[i]));
end;
end;
end;
Flush(OutFile);
CloseFile(OutFile);
SaveDialog1.FileName:='';
if MessageDlg('Исходный запрос был получен электронно?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
begin
SrcOpenDialog.Title:='Выберите файл исходного запроса';
SrcOpenDialog.Execute();
SaveDialog1.FileName:=MidStr(ExtractFileName(SrcOpenDialog.FileName),1,AnsiPos('.',ExtractFileName(SrcOpenDialog.FileName))-1);
if (InfType='ОСТАТКИ') then Pref:=OstPref;
if (InfType='ОПЕРАЦИИПОСЧ') then Pref:=OperPref;
if (InfType='НАЛСЧЕТОВ') then Pref:=NalschPref;
SaveDialog1.FileName:=Pref+SaveDialog1.FileName;
end
else // create name from file contents
begin
if (InfType='ОСТАТКИ') then
SaveDialog1.FileName:=OstPref+OstSrcPref+Bic+'_'+KodNO+DateResh+'_'+NomResh;
if (InfType='ОПЕРАЦИИПОСЧ') then
SaveDialog1.FileName:=OperPref+OperSrcPref+Bic+'_'+KodNO;
if (InfType='НАЛСЧЕТОВ') then
SaveDialog1.FileName:=NalschPref+NalschSrcPref+Bic+'_'+KodNO;
if ((InfType='ОПЕРАЦИИПОСЧ') or (InfType='НАЛСЧЕТОВ')) then
SaveDialog1.FileName:=SaveDialog1.FileName+DateZapr+'_'+NomZapr;
end;
SaveDialog1.FileName:=SaveDialog1.FileName+'.TXT';
ProgressBar1.Position:=0;
if SaveDialog1.Execute then
begin
if NumOutFiles > 1 then
begin // больше чем один файл - нумеруем с "1"
for i := 1 to NumOutfiles do
begin
// Str(i,StrFileNo);
StrFileNo:=Format('%.2d',[i]);
RetCode:=RenameFile(OpenDialog1.Filename+'.chk'+StrFileNo, ReplaceStr(SaveDialog1.FileName,'BV100','BV1'+StrFileNo));
if RetCode=false then
MessageDlg('Невозможно сохранить файл '+ReplaceStr(SaveDialog1.FileName,'BV100','BV1'+StrFileNo), mtError,[mbOk], 0, mbOk)
else
MessageDlg('Файл сохранен как: '+ReplaceStr(SaveDialog1.FileName,'BV100','BV1'+StrFileNo),mtInformation,[mbOk], 0, mbOk);
end;
end
else // один файл нумеруется с "0"
begin
StrFileNo:='01';
RetCode:=RenameFile(OpenDialog1.Filename+'.chk'+StrFileNo,SaveDialog1.FileName);
if RetCode=false then
MessageDlg('Невозможно сохранить файл '+SaveDialog1.FileName, mtError,[mbOk], 0, mbOk)
else
MessageDlg('Файл сохранен как: '+SaveDialog1.FileName,mtInformation,[mbOk], 0, mbOk);
end;
end;
end;
function TForm1.WriteLog(Level:Integer; S:String):String;
var
AColor:Integer;
begin
case Level of
ERR : AColor := clRed;
INFO: AColor := clLime;
WARN: AColor := clYellow;
else
AColor := clLime;
end;
with MProtocol do
begin
SelStart := Length(Text);
SelAttributes.Color := AColor;
Lines.Add(S);
end;
MProtocol.SelStart := MaxInt;
SendMessage(MProtocol.handle, EM_SCROLLCARET,0,0);
Result:=S;
end;
function TForm1.ToOEM(S:String):String;
{ ConvertAnsiToOem translates a string into the OEM-defined character set }
{$IFNDEF WIN32}
var
Source, Dest : array[0..255] of Char;
{$ENDIF}
begin
{$IFDEF WIN32}
SetLength(Result, Length(S));
if Length(Result) > 0 then
AnsiToOem(PChar(S), PChar(Result));
{$ELSE}
if Length(Result) > 0 then
begin
AnsiToOem(StrPCopy(Source, S), Dest);
Result := StrPas(Dest);
end;
{$ENDIF}
end; { ConvertAnsiToOem }
function TForm1.ToAnsi(S:String):String;
{ ConvertOemToAnsi translates a string into the OEM-defined character set }
{$IFNDEF WIN32}
var
Source, Dest : array[0..255] of Char;
{$ENDIF}
begin
{$IFDEF WIN32}
SetLength(Result, Length(S));
if Length(Result) > 0 then
OemToAnsi(PChar(S), PChar(Result));
{$ELSE}
if Length(Result) > 0 then
begin
OemToAnsi(StrPCopy(Source, S), Dest);
Result := StrPas(Dest);
end;
{$ENDIF}
end; { ConvertOemToAnsi }
function TForm1.FileSizeByName(Name:String): Integer;
var
F: File of byte;
begin
AssignFile(F, Name);
Reset(F);
Result:=FileSize(F);
CloseFile(F);
end;
function TForm1.isNum(const st:string): boolean;
var
i: Integer;
begin
isNum:=True;
for i := 1 to Length(st) do
if not (st[i] in ['0'..'9']) then isNum:=False;
end;
end.