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?
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;
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.
Have a set of Word-templates (files *.dot) and a little program, which create new files base on that templates. It's works fine, but the goal is to make all in one exe-file.
I see the solution is to move templates files into program resources. But I don't know, how then I will read them from resources. Tell me, please, how to do this.
Maybe you can advise me another solution.
Now, my code is:
procedure TfmMain.CreateDocument0;
var
TempleateFileName: string;
WordApp, Document: OleVariant;
procedure FillBookmark(BookmarkName, bText: string);
var
Range: OleVariant;
begin
if Document.Bookmarks.Exists(BookmarkName) then
begin
Range := Document.Bookmarks.Item(BookmarkName).Range;
Range.Text := bText;
end;
end;
begin
TempleateFileName := ExtractFilePath(Application.ExeName)+'Templates\0.dot';
try
WordApp := GetActiveOleObject('Word.Application');
except
try
WordApp := CreateOleObject('Word.Application');
except
on E: Exception do
begin
MessageBox(Self.Handle, PChar(E.Message), PChar(fmMain.Caption), MB_OK+MB_ICONERROR);
Exit;
end;
end;
end;
try
Document := WordApp.Documents.Add(TempleateFileName, False);
FillBookmark('ObjectType', edt0ObjectType.Text);
...
WordApp.Visible := True;
WordApp.Activate;
finally
WordApp := Unassigned;
end;
end;
That is, I should change this line:
Document := WordApp.Documents.Add(TempleateFileName, False);
Read not from file, but from program resource.
Word cannot open documents from memory. Not only does it not have such a feature, you must also bear in mind that Word executes in a separate process. It cannot see the memory in your process, even if it were able to open documents from memory.
If you do put the documents into linked resources then you will need to extract them to file before asking Word to open them.
I am using the following code to export an Open Office document as a pdf file using Delphi:
procedure TOOoWriter.SaveToPDF(FileName: string);
var
wProperties: variant;
begin
if not (fConnected and fDocumentOpened) then
abort;
wProperties := VarArrayCreate([0, 3], varVariant);
if fHTMLSrc then
wProperties[0] := MakePropertyValue('FilterName', 'writer_web_pdf_Export')
else
wProperties[0] := MakePropertyValue('FilterName', 'writer_pdf_Export');
wProperties[1] := MakePropertyValue('CompressionMode', '1');
wProperties[2] := MakePropertyValue('Pages', 'All');
wProperties[3] := MakePropertyValue('Overwrite', TRUE);
fDocument.StoreToURL('file:///'+ StringReplace(FileName, '\', '/', [rfIgnoreCase, rfReplaceAll]), wProperties);
end;
All is working well except:
it insists on opening the resultant pdf file (but not the OO file). This is problematic because I will be writing 100s of files without user interaction.
if the output pdf file does not exist I get an exception, but the file is created properly. The second time it works ok as the file was created the first time.
Are there solutions to these problems?
I'm struggling with the following:
The goal is to parametrize an automation server for openoffice and I'm programming in Delphi.
The piece of basic code I want to translate into Delphi code is:
Dim aProps(1) As New com.sun.star.beans.PropertyValue
aProps(0).Name = "FilterName"
aProps(0).Value = "Text - txt - csv (StarCalc)"
aProps(1).Name = "FilterOptions"
aProps(1).Value = sFilterOptions
My attempt in Delphi looks like
type TPrmRecord = packed Record
Name : String;
Value : String;
End;
Var
ooParams:Variant;
MyData : TPrmRecord;
Begin
ooParams:= VarArrayCreate([0, 1], varVariant);
MyData.Name := 'FilterName';
MyData.Value := 'Text - txt - csv (StarCalc)';
ooParams[0] := MyData;
MyData.Name := 'FilterOptions';
MyData.Value := '59/44,34,ANSI,1,';
ooParams[1] := MyData;
End;
This is not working does anyone have a suggestion how to tackle this?
Your TPrmRecord type is not what OO.org expects. You should not try to write your own types, but use those that OO.org exposes.
There is an LPGL-licensed toolbox for Delphi: Delphi OOo. In it you will find a unit OOoTools.pas, which exports a function CreateUnoStruct(). Use this and pass 'com.sun.star.beans.PropertyValue' as the name of the struct. You will get a Variant (or an array of those, depending on the other parameter value) back that you can use instead of TPrmRecord (something like the following, untested):
var
Params: Variant;
begin
Params := CreateUnoStruct('com.sun.star.beans.PropertyValue', 1);
Params[0].Name := 'FilterName';
Params[0].Value := 'Text - txt - csv (StarCalc)';
Params[1].Name := 'FilterOptions';
Params[1].Value := '59/44,34,ANSI,1,';
end;
It looks as though you're missing the creation of the COM class, which would be the equivalent of the New com.sun.star.beans.PropertyValue line in your code.
I suspect you need to import the type library into Delphi which would give you the objects, properties and methods you need to emulate the Basic behaviour.
Here is straight Delphi code without using Delphi OOo:
uses comobj;
var
OO_ServiceManager: OleVariant;
FileParams: OleVariant;
begin
OO_ServiceManager := CreateOleObject ('com.sun.star.ServiceManager');
FileParams := VarArrayCreate([0, 1], varVariant);
FileParams[0] := OO_ServiceManager.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
FileParams[0].Name := 'FilterName';
FileParams[0].Value := 'Text - txt - csv (StarCalc)';
FileParams[1] := OO_ServiceManager.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
FileParams[1].Name := 'FilterOptions';
FileParams[1].Value := '59/44,34,ANSI,1,';
end;
Have a look at this Thread in the german Delphi-PRAXiS forums. There is a whole delphi Unit posted doing some OOo automation.
use
var
ooParams:array[0..1] of TPrmRecord;
delphi uses strict type-casting, so this is causing an assignment error.