Created
October 23, 2025 21:38
-
-
Save Al-Muhandis/4ccea5793ef0e3b2ed4ac6df2d32abbc to your computer and use it in GitHub Desktop.
Пример генерации счета в FreePascal с помощью fcl-pdf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| unit invoice_pdf; | |
| {$mode objfpc}{$H+} | |
| interface | |
| uses | |
| Classes, SysUtils, fppdf, cmn_globals | |
| ; | |
| type | |
| { TInvoicePDFGenerator } | |
| TInvoicePDFGenerator = class | |
| private | |
| FCurrency: String; | |
| FFontFilePath: String; | |
| FFontName: String; | |
| FPayeeBankBIC: Int64; | |
| FPayeeBankName: String; | |
| FPayeeINN: Int64; | |
| FPayeeKPP: Int64; | |
| FPayerEmail: String; | |
| FPayerINN: String; | |
| FPayerKPP: String; | |
| FPayerName: String; | |
| FPayerPhone: String; | |
| FPayerTypeEnum: TPayerType; | |
| FPrice: Integer; | |
| FAcc, FCorrAcc: String; | |
| FDocNum: Integer; | |
| FPayeeName: String; | |
| FPaymentName: String; | |
| FPage: TPDFPage; | |
| FXBlockIndent, FXBlockIndent2: Integer; | |
| FY: Integer; | |
| procedure DrawLine(X, Y, L: Integer); | |
| function GetPayerType: String; | |
| procedure SetPayerType(AValue: String); | |
| procedure WriteText(X, Y: Integer; const S: string; aFont, aSize: Integer); | |
| procedure WriteBigText(X, Y: Integer; const S: string; aFont: Integer); | |
| procedure WriteSmallText(X, Y: Integer; const S: string; aFont: Integer); | |
| procedure WriteInfoBlockWithLine(const aInfoValue, aInfoName: String; aFont: Integer); | |
| procedure WriteInfoBlockWithLine(const aInfoValue1, aInfoName1, aInfoValue2, aInfoName2: String; aFont: Integer); | |
| public | |
| function Generate: TMemoryStream; | |
| property DocNum: Integer read FDocNum write FDocNum; | |
| property PayeeName: String read FPayeeName write FPayeeName; | |
| property PayeeINN: Int64 read FPayeeINN write FPayeeINN; | |
| property PayeeKPP: Int64 read FPayeeKPP write FPayeeKPP; | |
| property PayeeBankName: String read FPayeeBankName write FPayeeBankName; | |
| property PayeeBankBIC: Int64 read FPayeeBankBIC write FPayeeBankBIC; | |
| property PaymentName: String read FPaymentName write FPaymentName; | |
| property PayerType: String read GetPayerType write SetPayerType; | |
| property PayerTypeEnum: TPayerType read FPayerTypeEnum write FPayerTypeEnum; | |
| property PayerName: String read FPayerName write FPayerName; | |
| property PayerEmail: String read FPayerEmail write FPayerEmail; | |
| property PayerPhone: String read FPayerPhone write FPayerPhone; | |
| property PayerINN: String read FPayerINN write FPayerINN; | |
| property PayerKPP: String read FPayerKPP write FPayerKPP; | |
| property PayeeBankCorrAcc: String read FCorrAcc write FCorrAcc; | |
| property PayeeBankAcc: String read FAcc write FAcc; | |
| property Price: Integer read FPrice write FPrice; | |
| property Currency: String read FCurrency write FCurrency; | |
| property FontFilePath: String read FFontFilePath write FFontFilePath; | |
| property FontName: String read FFontName write FFontName; | |
| end; | |
| function InvoiceFullID(const aText: String; aDocNum: Integer; aDate: TDate): String; | |
| implementation | |
| function InvoiceFullID(const aText: String; aDocNum: Integer; aDate: TDate): String; | |
| begin | |
| Result:=Format(aText, [aDocNum, FormatDateTime('dd.mm.yyyy', aDate)]); | |
| end; | |
| { TInvoicePDFGenerator } | |
| procedure TInvoicePDFGenerator.DrawLine(X, Y, L: Integer); | |
| begin | |
| FPage.MoveTo(X, Y); | |
| FPage.DrawLine(X,Y, x+L, Y, 0.5, False); | |
| FPage.StrokePath; | |
| end; | |
| function TInvoicePDFGenerator.GetPayerType: String; | |
| begin | |
| Result:=PayerTypeToString(FPayerTypeEnum); | |
| end; | |
| procedure TInvoicePDFGenerator.SetPayerType(AValue: String); | |
| begin | |
| FPayerTypeEnum:=StringToPayerType(AValue); | |
| end; | |
| procedure TInvoicePDFGenerator.WriteText(X, Y: Integer; const S: string; aFont, aSize: Integer); | |
| begin | |
| FPage.SetFont(aFont, aSize); | |
| FPage.WriteText(X, Y, S); | |
| end; | |
| procedure TInvoicePDFGenerator.WriteBigText(X, Y: Integer; const S: string; aFont: Integer); | |
| begin | |
| WriteText(X, Y, S, aFont, 12); | |
| end; | |
| procedure TInvoicePDFGenerator.WriteSmallText(X, Y: Integer; const S: string; aFont: Integer); | |
| begin | |
| WriteText(X, Y, S, aFont, 9); | |
| end; | |
| procedure TInvoicePDFGenerator.WriteInfoBlockWithLine(const aInfoValue, aInfoName: String; aFont: Integer); | |
| begin | |
| WriteBigText(FXBlockIndent, FY, aInfoValue, aFont); FY -= 2; | |
| DrawLine(FXBlockIndent, FY, 140); FY -= 3; | |
| WriteSmallText(FXBlockIndent+5, FY, aInfoName, aFont); FY -= 8; | |
| end; | |
| procedure TInvoicePDFGenerator.WriteInfoBlockWithLine(const aInfoValue1, aInfoName1, aInfoValue2, aInfoName2: String; | |
| aFont: Integer); | |
| begin | |
| WriteBigText(FXBlockIndent, FY, aInfoValue1, aFont); WriteBigText(FXBlockIndent2, FY, aInfoValue2, aFont); FY -= 2; | |
| DrawLine(FXBlockIndent, FY, 60); DrawLine(FXBlockIndent2, FY, 60); FY -= 3; | |
| WriteSmallText(FXBlockIndent+5, FY, aInfoName1, aFont); WriteSmallText(FXBlockIndent2+5, FY, aInfoName2, aFont); FY -= 8; | |
| end; | |
| function TInvoicePDFGenerator.Generate: TMemoryStream; | |
| var | |
| aDoc: TPDFDocument; | |
| aFont: Integer; | |
| aSection: TPDFSection; | |
| InvoiceNo, aInvoiceNum: string; | |
| begin | |
| Result := TMemoryStream.Create; | |
| aDoc := TPDFDocument.Create(nil); | |
| try | |
| aDoc.StartDocument; | |
| aSection := aDoc.Sections.AddSection; | |
| FPage := aDoc.Pages.AddPage; | |
| aSection.AddPage(FPage); | |
| if FFontFilePath.IsEmpty then | |
| aFont := aDoc.AddFont(FFontName) | |
| else | |
| aFont := aDoc.AddFont(FFontFilePath, FFontName); | |
| FY := Round(FPage.GetPaperHeight) - 10; | |
| InvoiceNo := InvoiceFullID('Счет на оплату № %d от %s г.', DocNum, Date); | |
| WriteBigText(40, FY, InvoiceNo, aFont); FY -= 16; | |
| FXBlockIndent:=40; | |
| FXBlockIndent2:=120; | |
| WriteInfoBlockWithLine(PayeeBankName, 'Банк получателя', aFont); | |
| WriteInfoBlockWithLine(PayeeBankBIC.ToString, 'БИК банка получателя', PayeeBankCorrAcc, | |
| 'Номер корр.счета банка получателя', aFont); | |
| WriteInfoBlockWithLine(PayeeINN.ToString, 'ИНН получателя', PayeeKPP.ToString, 'КПП получателя', aFont); | |
| WriteInfoBlockWithLine(PayeeBankAcc, 'Счет получателя платежа', aFont); | |
| WriteInfoBlockWithLine(PayeeName, 'Получатель платежа', aFont); | |
| aInvoiceNum:=Format(PaymentName, [InvoiceFullID('№ %d от %s г.', DocNum, Date)]); | |
| WriteInfoBlockWithLine(aInvoiceNum, 'Наименование платежа', aFont); | |
| FY -= 8; | |
| WriteBigText(FXBlockIndent+40, FY, Format('Сумма платежа: %s', [CurrencyToStr(FPrice, FCurrency)]), aFont); FY -= 8; | |
| WriteBigText(FXBlockIndent+40, FY, 'НДС не облагается', aFont); FY -= 8; | |
| FY -= 8; | |
| WriteBigText(FXBlockIndent+5, FY, 'Плательщик: ' + PayerName, aFont); FY -= 8; | |
| if FPayerTypeEnum=pteEntity then | |
| begin | |
| WriteBigText(FXBlockIndent+5, FY, 'ИНН плательщика: ' + PayerINN, aFont); FY -= 8; | |
| WriteBigText(FXBlockIndent+5, FY, 'КПП плательщика: ' + PayerKPP, aFont); FY -= 8; | |
| end; | |
| WriteBigText(FXBlockIndent+5, FY, 'Email: ' + PayerEmail, aFont); | |
| WriteBigText(FXBlockIndent2+5, FY, 'Тел.: +' + PayerPhone, aFont); FY -= 12; | |
| aDoc.SaveToStream(Result); | |
| finally | |
| aDoc.Free; | |
| end; | |
| Result.Position := 0; | |
| end; | |
| end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment