I'm using Gnostice PDF Toolkit v5.0.0.457, and it works fine to operate with PDF files (merge files, split files, insert blank pages, insert text watermarks, insert image watermarks, print files, ...).
But I always have big memory leaks that prevent me to use it on the server side.
Am I doing something wrong in this code (it simply adds a text watermark to a PDF file) ? :
implementation
{$R *.dfm}
uses gtCstPDFDoc, gtPDFDoc;
procedure TTestForm.btnTestWatermarkClick(Sender: TObject);
var PDFDoc: TgtPDFDocument;
txtWatermark: TgtTextWatermarkTemplate;
begin
PDFDoc := TgtPDFDocument.Create(nil);
txtWatermark := TgtTextWatermarkTemplate.Create;
try
PDFDoc.LoadFromFile('C:\Temp\Test.pdf');
txtWatermark.FontEncoding := feWinAnsiEncoding ;
txtWatermark.Text := 'Hello World';
txtWatermark.Font.Name := 'Arial';
txtWatermark.Font.Size := 12;
txtWatermark.Font.Color := clBlack;
txtWatermark.X := 150;
txtWatermark.Y := 150;
txtWatermark.HorizPos := hpCustom;
txtWatermark.VertPos := vpCustom;
txtWatermark.Overlay := True;
PDFDoc.InsertWatermark(txtWatermark, '1');
PDFDoc.SaveToFile('C:\Temp\TestOutput.pdf');
finally
PDFDoc.Reset;
PDFDoc.Free;
txtWatermark.Free;
end;
end;
This simple example already generates important memory leaks.
PS: I know that the best place to get support is the manufacturer itself, but my subscription ended a year ago.
Thank you
Update: We have re-subscribed with Gnostice, and the current version has the memory leaks solved. Thanks to all.
Related
I am a beginner in Delphi (I use Delphi 2010 because of school) and I am trying to get an output textfile with a list of pastes that a pastebin user has created, but I am not exactly sure how to do it. On Pastebin.com (PastebinAPI), they explain how the API works, but I can't get it working on Delphi.
Here is what I have coded so far (I blurred out my details):
procedure TfrmLogin.imgLoginButtonClick(Sender: TObject);
var
sSource, sAPI_Dev_Key, sAPI_User_Key, sAPI_Results_Limit, sAPI_Option,
sListPasteLink: String;
begin
sSource := 'https://pastebin.com/api/api_post.php/';
sAPI_Dev_Key := 'xxxxxxxxxxxxxxxxxxxxxxxx/';
sAPI_User_Key := 'xxxxxxxxxxxxxxxxxxxxxxx/';
sAPI_Results_Limit := '1000/';
sAPI_Option := 'list';
sListPasteLink := sSource + sAPI_Dev_Key + sAPI_User_Key +
sAPI_Results_Limit + sAPI_Option;
end;
I am not sure what to do after this, how do I POST this generated link in Delphi to get the list of pastes created?
I tried copying the generated link and pasting it in my web browser, but Pastebin says This page has been removed!
Any help would be appreciated, thank you
Here is an example. Drop a TButton, a TMemo, a TIdHTTP and a TIdSSLIOHandlerSocketOpenSSL on a form. You will also need to copy libeay32.dll and ssleay32.dll into your application directory (they are provided somehere in the directory where Delphi was installed).
procedure TForm1.Button1Click(Sender: TObject);
var
Params: TStringList;
begin
Params := TStringList.Create;
Params.Add('api_dev_key=*****');
Params.Add('api_user_key=*****');
Params.Add('api_option=list');
try
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1_1, sslvTLSv1_2];
IdHTTP1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
Memo1.Text := IdHTTP1.Post('https://pastebin.com/api/api_post.php', Params);
finally
Params.Free;
end;
end;
With many thanks to f.i. TLama I could set up a workaround for opening a file, replacing some fields and store the result to pdf using Delphi 2007. I have a document opened in OpenOffice like this:
FileParams := VarArrayCreate([0, 0], varVariant);
FileProperty := StarOffice.Bridge_GetStruct ('com.sun.star.beans.PropertyValue');
FileProperty.Name := 'Hidden';
FileProperty.Value := true;
FileParams[0] := FileProperty;
StarDocument := StarDesktop.LoadComponentFromURL(AFileURL, '_blank', 0, FileParams);
Where AFileURL is the full pathname starting with 'file:///'
Later I replace the fields in this document with the option I discovered elsewhere on this site:
FileReplace := StarDocument.CreateReplaceDescriptor;
FileReplace.SearchCaseSensitive := False;
FileReplace.SetSearchString(zoekstring);
FileReplace.SetReplaceString(vervang);
StarDocument.ReplaceAll(FileReplace);
And then store the document to pdf.
Actually the file is a doc-file simply copied to a file with extension odt.
Everything is working fine if I first load the document in OpenOffice and save as Openoffice odt-document, but I want to do that programmaticly.
So, before being able to replace the WORD-fields (like «11») I want to store the odt-file as a proper OpenOffice document, because like this Open Office does not recognize the fields to replace.
I tried:
if StarDocument.hasLocation then
try
StarDocument.Store();
except
showmessage('unable to save');
end;
Reading OpenOffice documentation gave me the idea that this might work, but it does not.
I also tried:
function CreateProperty(const AName: AnsiString; AValue: Variant): Variant;
begin
Result := StarOffice.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
Result.Name := AName;
Result.Value := AValue;
end;
FilterParams := VarArrayCreate([0, 0], varVariant);
FilterParams[0] := CreateProperty('FilterName', 'Text');
StarDocument.StoreAsURL(AFileURL,FilterParams);
Does not work either. I get a Fatal Error from Open Office. Who knows what I am missing?
I want to align a text to center and I have no idea on how to achieve it.
Here is my code:
try
MsWord := GetActiveOleObject('Word.Application');
except
try
MsWord := CreateOleObject('Word.Application');
MsWord.Visible := True;
except
Exception.Create('Error');
end;
end;
MSWord.Documents.Add;
MSWord.Selection.Font.Size := 22;
MSWord.Selection.Font.Bold := true;
MSWord.Selection.TypeText(#13#10);
MSWord.Selection.TypeText('I want this to be center-aligned');
...
MSWord.ActiveDocument.SaveAs('C:\doc2.doc');
Please help.
Thanks
This works for me:
procedure TForm1.Button1Click(Sender: TObject);
var
MSWord : OleVariant;
begin
try
MsWord := GetActiveOleObject('Word.Application');
except
try
MsWord := CreateOleObject('Word.Application');
MsWord.Visible := True;
except
Exception.Create('Error');
end;
end;
MSWord.Documents.Add;
MSWord.Selection.Font.Size := 22;
MSWord.Selection.Font.Bold := true;
MSWord.Selection.TypeText(#13#10);
MSWord.Selection.TypeText('I want this to be center-aligned');
MSWord.Selection.ParagraphFormat.Alignment := wdAlignParagraphCenter;
MSWord.ActiveDocument.SaveAs('C:\doc2.doc');
end;
Btw, the way to find the answer yourself is to go into Word, start recording a macro, perform the action, stop recording then edit the macro to see what code Word generates. Converting that to Delphi is usually fairly trivial if you're using late binding (accessing Word from Delphi via an OleVariant) but can be a bit long winded if you're using early binding, because early binding requires all parameters to be specified, whereas late binding lets you leave most of them out.
I have multiple RVSystems set up each with there own unit to print one report each. I have a program where the user can select from a list of which ones they want to see.
The problem I'm trying to solve is how to combine the ones the user selects so they don't have to preview/print for each one they choose. I don't want to use a RVProject because they are all code based and I am not using a .rav file at all. Thanks!!!
I have looked at the Nevrona tip #41 which is supposed to address but it uses a RVProject with a .rav file to access the separate reports.
Nick
WPCubed wPDF can print multiple RAVE report into one PDF file:
http://www.wpcubed.com/manuals/wpdf/index.html?ravereport.htm
Example 2:
Render multiple NDR files directly to the PDF file 'c:\rave.pdf'. It uses an open dialog to let you choose the files.
procedure TForm1.Button1Click(Sender: TObject);
var
OpenDialog: TOpenDialog;
RvRenderWPDF: TRvRenderWPDF;
WPPDFPrinter: TWPPDFPrinter;
FileStream: TFileStream;
output: string;
i: Integer;
begin
OpenDialog := TOpenDialog.Create(Self);
OpenDialog.Options := [ofAllowMultiSelect];
RvRenderWPDF := TRvRenderWPDF.Create(Self);
WPPDFPrinter := TWPPDFPrinter.Create(Self);
try
OpenDialog.Filter := 'NDF Files|*.NDR';
RvRenderWPDF.PDFPrinter := WPPDFPrinter;
RvRenderWPDF.Active := TRUE;
WPPDFPrinter.AutoLaunch := TRUE;
WPPDFPrinter.CompressStreamMethod := wpCompressFastFlate;
if OpenDialog.Execute then
begin
output := 'dummy';
WPPDFPrinter.Filename := 'c:\rave.pdf';
WPPDFPrinter.BeginDoc;
try
for i := 0 to OpenDialog.Files.Count - 1 do
begin
FileStream := TFileStream.Create(OpenDialog.Files[i], fmOpenRead);
try
RvRenderWPDF.PrintRender(FileStream, output);
finally
FileStream.Free;
end;
end;
finally
WPPDFPrinter.EndDoc;
end;
end;
finally
OpenDialog.Free;
RvRenderWPDF.Free;
WPPDFPrinter.Free;
end;
end;
Also maybe You can use Gnostice eDocEngine to merge Rave Reports:
http://www.gnostice.com/nl_article.asp?id=247&t=Export_From_Rave_Reports_To_PDF_And_Other_Formats
Programmatic Export From Rave Report Snapshot File
In this example, eDocEngine will be used to export a Rave Reports report from an NDR (Rave Report snapshot) file.
Open the IDE and create a VCL forms application.
Drop three Rave Reports export interface components (TgtRaveExportInterface) on the form.
Drop a PDF engine (TgtPDFEngine), RTF engine (TgtRTFEngine) and XHTML engine (TgtXHTMLEngine) components on the form.
Add a button to the form and set this procedure for its click event handler
procedure TForm5.Button2Click(Sender: TObject);
begin
// Set output engines for the report export components
gtRaveExportInterface1.Engine := gtPDFEngine1;
gtRaveExportInterface2.Engine := gtRTFEngine1;
gtRaveExportInterface3.Engine := gtXHTMLEngine1;
// Disable output preferences dialog boxes
gtPDFEngine1.Preferences.ShowSetupDialog := false;
gtRTFEngine1.Preferences.ShowSetupDialog := false;
gtXHTMLEngine1.Preferences.ShowSetupDialog := false;
// Set output file name of the engines
gtPDFEngine1.FileName := 'eDoc_Rave_Demo.pdf';
gtRTFEngine1.FileName := 'eDoc_Rave_Demo.rtf';
gtXHTMLEngine1.FileName := 'eDoc_Rave_Demo.html';
// Export a Rave Reports snapshot file to PDF, RTF and XHTML
gtRaveExportInterface1.RenderDocument('eDoc_Rave.ndr');
gtRaveExportInterface2.RenderDocument('eDoc_Rave.ndr');
gtRaveExportInterface3.RenderDocument('eDoc_Rave.ndr');
end;
From our application we use OLE automation to build a fairly complex Word-document. I would like to make Word invisible while the document is being made, since there is a lot of pasting and insertions that takes quite a long time.
I use the following code to establish a Word connection:
function ConnectToWord : TWordAutomationResult;
begin
WordApp := TWordApplication.Create(nil);
try
WordApp.Connect;
WordApp.Visible := false;
except on E: Exception do
begin
Result := waeErrorConnectingToWord;
exit;
end;
end;
end;
And I use the following code to open an existing document, which is then edited by my application.
function TWordAUtomation.OpenDocument(aFileName: string) : WordDocument;
var vFileName,
vConfirmConversions,
vReadOnly,
vAddToRecentFiles,
vPasswordDocument,
vPasswordTemplate,
vRevert,
vWritePasswordDocument,
vWritePasswordTemplate,
vFormat,
vEncoding,
vVisible,
vOpenConflictDocument,
vOpenAndRepair,
vWdDocumentDirection,
vNoEncodingDialog : OleVariant;
begin
Result := nil;
if not FileExists(aFileName) then exit;
vFileName := aFileName;
vConfirmConversions := True;
vReadOnly := False;
vAddToRecentFiles := False;
vPasswordDocument := EmptyParam;
vPasswordTemplate := EmptyParam;
vRevert := True;
vWritePasswordDocument := EmptyParam;
vWritePasswordTemplate := EmptyParam;
vFormat := wdOpenFormatAuto;
vEncoding := EmptyParam;
vVisible := False; //Document should be invisible
vOpenConflictDocument := EmptyParam;
vOpenAndRepair := EmptyParam;
vWdDocumentDirection := EmptyParam;
vNoEncodingDialog := EmptyParam;
Result := WordApp.Documents.Open(vFileName, vConfirmConversions, vReadOnly, vAddToRecentFiles, vPasswordDocument, vPasswordTemplate, vRevert, vWritePasswordDocument, vWritePasswordTemplate, vFormat, vEncoding, vVisible, vOpenAndRepair, vWdDocumentDirection, vNoEncodingDialog);
end;
It works on my computer! (TM)
For some of our customers Word remains visible during the editing process. What reasons can there be for this? As far as I can tell the problem arises for customers that use some sort of remote computing, like managed clients etc. Are there some additional properties that deals with application visibility that only have effect during remote desktop connections etc? I'm not very knowledgeable about such things :-(
I'm maintaining the Word automation for our software and also had reports of Word windows popping up in Citrix clients. I don't know what causes this and how to get rid of it.
There is only one way I can simulate Word becoming visible again and that is opening a Word-document while your application is processing. But I don't think that is the cause of your problems.
PS: You call TWordApplication.Connect and then you set Visible to False. Know that when you call Connect and you haven't changed ConnectKind, it will connect to a running instance of Word. When your client is editing a document this document will suddenly dissappear. Perhaps it is better to set ConnectKind to NewInstance so you always work in a new winword.exe process. The existing winword.exe will remain available for your client and he can continue working at his document while your application is processing the other.
Ofcourse this approach has some drawbacks too:
When your client opens a new Word-document, it is opened in your instance of Word
You can get errors on Normal.dot being modified by another application
Instead of using TWordApplication, use CreateOLEObject:
var WordApp: Variant;
procedure OpenWordFIle( const Filename: String );
begin
WordApp := CreateOLEObject('Word.Application');
WordApp.Visible := False;
WordApp.Documents.Open( Filename );
Application.ProcessMessages;
end;
To close it gracefully:
procedure CloseWordFile;
begin
WordApp.ActiveDocument.Close( $00000000 );
WordApp.Quit;
WordApp := unassigned;
end;
If you don't close it, Word application will be open even after your close your Delphi application.
Some useful resources where you can find more options to open/close Word Files:
http://msdn.microsoft.com/en-us/library/office/ff835182.aspx
How can I call documents.open and avoid the 'file in use' dialog?
in my case it happend similar as you described. I looks the application is still running even if you disconnect. The first time it will not be shown, but as soon as you have a second open then the application will be visible. in My case it helped to explicitly quite the application. It quit's only the instance that is doing the work in background. Another open document edited by the local user will not be touched.
WordDocument.Disconnect;
**WordApplication.Quit;**
WordApplication.Disconnect;