Open a libreoffice mail merged textdocument directly with swriter - openoffice.org

I need help with opening the result of my mail merge operations directly in an new writer document.
Object mailMergeService = mcf.createInstanceWithContext(mailMergePackage, context);
XPropertySet mmProperties = UnoRuntime.queryInterface(XPropertySet.class, mailMergeService);
mmProperties.setPropertyValue("DocumentURL", templatePath);
mmProperties.setPropertyValue("DataSourceName", dbName);
mmProperties.setPropertyValue("CommandType", mmCommandType);
mmProperties.setPropertyValue("Command", mmCommand);
mmProperties.setPropertyValue("OutputType", mmOutputType);
// mmProperties.setPropertyValue("OutputURL", templateDirectory);
// mmProperties.setPropertyValue("FileNamePrefix", mmFileNamePrefix);
// mmProperties.setPropertyValue("SaveAsSingleFile", mmSaveAsSingleFile);
The mmOutputType is set as MailMergeType.SHELL
The LibreOffice API documentation says
"The output is a document shell.
The successful mail marge returns a XTextDocument based component."
So I've tried something like this
XJob job = UnoRuntime.queryInterface(XJob.class, mailMergeService);
Object mergedTextObject = job.execute(new NamedValue[0]);
String url = "private:factory/swriter";
loader.loadComponentFromURL(url, "_blank", 0, new PropertyValue[0]);
XTextDocument mergedText = UnoRuntime.queryInterface(XTextDocument.class, mergedTextObject);
XTextCursor cursor = mergedText.getText().createTextCursor();
cursor.setString(mergedText.getText().getString());
I guess I have to pass the XTextDocument component to the url-argument of the loadComponentFromURL method but I didnt find the right way to do that.
When I change the OutputType to MailMergeType.FILE the result is generated in a given directory and I can open the file and see that the mail merge succeeded. But this is not what my application should do.
Does someone know how I can open the result of the mail merge directly in an new writer document without saving the result to the hard drive?
Sincerly arthur

Hey guys I've found a simple way to open the result of my mail merge process directly.
The relevant snippets are these
XJob job = UnoRuntime.queryInterface(XJob.class, mailMergeService);
Object mergedTextObject = job.execute(new NamedValue[0]);
XTextDocument mergedText = UnoRuntime.queryInterface(XTextDocument.class, mergedTextObject);
mergedText.getCurrentController().getFrame().getContainerWindow().setVisible(true);
The last line of code made the window appear with the filled mail merge result.
I also don't need this line anymore
loader.loadComponentFromURL("private:factory/swriter", "_blank", 0, new PropertyValue[0]);
The document opens as a new instance of a swriter document. If you want to save the result as a file you can do this
mergedText.getCurrentController().getFrame().getContainerWindow().setVisible(true);
XStorable storeMM = UnoRuntime.queryInterface(XStorable.class, mergedText);
XModel modelMM = UnoRuntime.queryInterface(XModel.class, mergedText);
storeMM.storeAsURL(outputDirectory + outputFilename, modelMM.getArgs());
Sincerly
Arthur

What version of LO are you using? The SHELL constant has only been around since LO 4.4, and it is not supported by Apache OpenOffice yet, so it could be that it isn't fully implemented. However this code seems to show a working test.
If it is returning an XTextDocument, then normally I would assume the component is already open. However it sounds like you are not seeing a Writer window appear. Did you start LO in headless mode? If not, then maybe the process needs a few seconds before it can display.
Object mergedTextObject = job.execute(new NamedValue[0]);
Thread.sleep(10000);
Anyway to me it looks like your code has a mistake in it. These two lines would simply insert the text onto itself:
XTextCursor cursor = mergedText.getText().createTextCursor();
cursor.setString(mergedText.getText().getString());
Probably you intended to write something like this instead:
XTextDocument mergedText = UnoRuntime.queryInterface(XTextDocument.class, mergedTextObject);
String url = "private:factory/swriter";
XComponent xComponent = loader.loadComponentFromURL(url, "_blank", 0, new PropertyValue[0]);
XTextDocument xTextDocument = (XTextDocument)UnoRuntime.queryInterface(XTextDocument.class, xComponent);
XText xText = (XText)xTextDocument.getText();
XTextRange xTextRange = xText.getEnd();
xTextRange.setString(mergedText.getText().getString());
One more thought: getString() might just return an empty string if the entire document is in a table. If that is the case then you could use the view cursor or enumerate text content.
EDIT:
To preserve formatting including tables, you can do something like this (adapted from https://blog.oio.de/2010/10/27/copy-and-paste-without-clipboard-using-openoffice-org-api/):
// Select all.
XController xMergedTextController = mergedText.getCurrentController();
XTextViewCursorSupplier supTextViewCursor =
(XTextViewCursorSupplier) UnoRuntime.queryInterface(
XTextViewCursorSupplier.class, xMergedTextController);
XTextViewCursor oVC = supTextViewCursor.getViewCursor();
oVC.gotoStart(False) // This would not work if your document began with a table.
oVC.gotoEnd(True)
// Copy and paste.
XTransferableSupplier xTransferableSupplier = UnoRuntime.queryInterface(XTransferableSupplier.class, xMergedTextController);
XTransferable transferable = xTransferableSupplier.getTransferable();
XController xController = xComponent.getCurrentController();
XTransferableSupplier xTransferableSupplier_newDoc = UnoRuntime.queryInterface(XTransferableSupplier.class, xController);
xTransferableSupplier_newDoc.insertTransferable(transferable);

Related

How to convert raw String with a FIX message to QuickFIX/J Message object

What is the recommended way to convert a raw String, with one FIX message, to one QuickFIX/J Message object of the appropriate type, like one quickfix.fix44.ExecutionReport object?
I only have to deal with the FIX 4.4 version.
I found two options at this thread on Quickfixj-users mailing list.
I adapted these options to my situation and I was able to convert the message successfully in two different ways.
Example of a FIX message:
8=FIX.4.49=11035=834=749=EXEC52=20211014-19:39:25.75856=BANZAI6=011=114=10017=137=139=154=155=IBM150=2151=40010=237
I'd like to know which of the options below is better or if both are wrong and there's a better way.
Thanks in advance.
1 Option
quickfix.Message rawMessage = new quickfix.Message(rawMessageString);
// Example of MsgType = 8
MsgType msgType = new MsgType();
rawMessage.getHeader().getField(msgType);
MessageFactory messageFactory = new DefaultMessageFactory(ApplVerID.FIX44);
quickfix.Message message = messageFactory.create("FIX.4.4", msgType.getValue());
message.fromString(messageString, null, false, true);
// message.getName() = quickfix.fix44.ExecutionReport
System.out.println(message.getName() = " + message.getClass().getName());
2 Option
MessageFactory messageFactory = new DefaultMessageFactory(ApplVerID.FIX44);
quickfix.Message messageFromMessageUtils = quickfix.MessageUtils.parse(messageFactory, null, rawMessageString);
// message.getName() = quickfix.fix44.ExecutionReport
System.out.println(message.getName() = " + message.getClass().getName());
Data Dictionary
In the above tests, I didn't use a Data Dictionary, but in my real application I'll use one.
What I especially dislike about option 1 is that you need to construct two messages. One for the extraction of the MsgType and afterwards the actual message. Seems unnecessary to me.
If you are only using FIX4.4 I would go for the second option because it does all the magic for you, i.e. extracts the needed things like BeginString and MsgType from the raw String.
Downside: it will only work up to and including FIX4.4 since MessageUtils.parse() does only consider the BeginString (not the ApplVerID).
However, this should be no problem for your use case.
P.S.: If you ever need to parse messages for FIX5.0 and upwards, use the following (which is basically option 1 but without constructing a message to get the MsgType):
String msgType = MessageUtils.getMessageType(rawMessageString);
MessageFactory messageFactory = new DefaultMessageFactory(ApplVerID.FIX50); // FIX5.0 for example
quickfix.Message message = messageFactory.create("FIXT.1.1", ApplVerID.FIX50, msgType);
message.fromString(rawMessageString, dd, false, true);
P.P.S.: Not of interest for your use case but for the sake of completeness: you could also use one of the quickfix.Message(String) constructors but that would not return you a message of the correct type. Just a general quickfix.Message.

Dart: getElementsByClassName returns a 0 element list but the data is there

I'm writing a function that will parse certain websites and fetch data from there, which will be used to create instances of a class. I'm able to successfully extract the data when it is retrieved using the getElementById() function, but for some reason, the getElementsByClassName() always returns a node list with 0 elements.
The site I'm currently parsing is here.
If you search for 'datas-nev', you will find exactly one match:
<p class="datas-nev"><b>Kutya neve: </b>Jhonny</p>
And here is the code use for parsing:
import 'package:html/parser.dart' show parse;
...
final response = await http.get(URL);
var document = parse(response.body);
var detailsContainer = document.getElementById('husky_details_container_right');
var dogName = new List<Node>();
dogName = document.getElementsByClassName('datas-nev');
The contents of the detailsContainer can be extracted successfully, for example this gives me back a string of relevant data I will use later:
var humanBehaviourValue;
try { humanBehaviourValue = detailsContainer.nodes[1].nodes[19].nodes[1].nodes[7].nodes[1].toString(); }
catch (e) { humanBehaviourValue = 'N/A'; }
But when I check the value of dogName in the debug window, I get the following:
dogName = {_growableList} size = 0
I already tried initializing the dogName 'properly' by List<Node> dogName = new List<Node>(); but it didn't help. I also tried other datas-* values, but it seems the parser can't find them. I even tried using just datas (because that is a div, while others are paragraphs), but that didn't help either.
Basically I could just hardwire the name and some data (breed, color, etc) as those never really change, but the location of the shelter can change, and keeping it up-to-date by scraping the data seems better than pushing updates out manually. That means I mostly need the value of datas-helyszin but that isn't parsed either.
As #Günter Zöchbauer pointed out, the code actually works. I was just looking for the value too soon, before it was actually fetched...

Export SSRS report directly without rendering it on ReportViewer

I have a set of RDL reports hosted on the report server instance. Some of the report renders more than 100,000 records on the ReportViewer. So that it takes quite long time to render it on the Viewer. So, we decided to go with Export the content directly from the server based on the user input parameters for the report as well as export file format.
Main thing here, I do not want the user to wait until the export file available for download. Rather, User can submit the action and can proceed to do other works. In the background, the program has to export the file to some physical location. When the download will be available, the user will be informed with some notification about the exported file.
I found the way in this Link. I need to know what are the ways to achieve the above mentioned functionality as well as how to pass the input parameters for the report. Pl suggest me.
Note: I was using XML as datasource for the rdl reports.
EDIT
I found something useful and did the coding like the below,
string path = ServerURL +"?" + _reportFolder + "ReportName&rs:Command=Render&rs:Format=PDF";
WebRequest req = WebRequest.Create(path);
string reportParametersQT = String.Empty;
req.Credentials = CredentialCache.DefaultNetworkCredentials;
WebResponse response = req.GetResponse();
Stream stream = response.GetResponseStream();
//screen.Response.Clear();
string enCodeFileName = HttpUtility.UrlEncode("fileName.pdf", System.Text.Encoding.UTF8);
// The word attachment in Addheader is used to directly show the save dialog box in browser
Response.AddHeader("content-disposition", "attachment; filename=" + enCodeFileName);
Response.BufferOutput = false; // to prevent buffering
Response.ContentType = response.ContentType;
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
{
Response.OutputStream.Write(buffer, 0, bytesRead);
}
Response.End();
I am able to download the exported file. But need to save the file in physical location instead of downloading. I dont know how to do that.
Both of these are very easy to do. You essentially just pass the parameters in the URL that you're calling, for example for a parameter called "LearnerList" you add &LearnerList=12345 to the URL. For exporting, add an additional paramter for Format=PDF (or whatever you want the file as) to get the report to export as a PDF instead of generating in Report Viewer.
Here's an example URL:
https://reporting.MySite.net/ReportServer/Pages/ReportViewer.aspx?/Users+Folders/User/My+Reports/Learner+Details&rs:Format=PDF&LearnerList=202307
Read these two pages, and you should be golden:
https://msdn.microsoft.com/en-us/library/ms155391.aspx
https://msdn.microsoft.com/en-us/library/ms154040.aspx

Actionscript 2.0, simple file input

I'm pretty inexperienced with actionscript, and I'm having the hardest time trying to figure out how to load variables from a file and send it to a dynamic text box.
The content of an external file, "varload.txt", is "name1=John".
Here is actionscript of my flash file:
myVars = new LoadVars();
myVars.onLoad = function(){
trace(this.name1); //prints "John" as expected
myname=this.name1;
}
myVars.sendAndLoad("varload.txt", myVars);
mytextbox.text=myname; //undefined
I'm guessing it's a scope issue, but I can't find much online about global variables in actionscript, so I'm not sure how to fix this.
How do I get mytextbox.text to equal John?
The issue is that onLoad is asynchronous (called once the file has loaded, not immediately).
You'll have to define the text within the onLoad function:
myVars = new LoadVars();
myVars.onLoad = function()
{
mytextbox.text = this.name1;
}
myVars.sendAndLoad("varload.txt", myVars);
With your code, you're trying to set the content of the text box to being data that doesn't exist / hasn't loaded yet.

strip carriage returns from xml serialization in F#

update: some background - i use the xml file to generate a set of pdfs (through a java application that drives JasperReports). all the reports are coming out blank when I use this new xml file. I've ruled out network problems because I use an old xml file from the same server that I run the java application with the new xml file. I've compared the two files (old-good one and new-bad one) using a hex-editor and my first clue is that there are carriage returns in the new file and none in the old one. this may not fix the issue, but I'd like to eliminate it from the equation.
I think I need to remove all the carriage returns from my xml file in order for it to work as I need it to. In my travels, the closest I found is this:
.Replace("\r","")
but where do I use it in the following code? I create my data model, create a root, and pass that to the serializer. At what point can I say "remove carriage returns?"
let def = new reportDefinition("decileRank", "jasper", new template("\\\\server\\location\\filename.jrxml", "jrxml"))
let header = new reportDefinitions([| def |])
let root = reportGenerator(header, new dbConnection(), new reports(reportsArray))
let path = sprintf "C:\\JasperRpt\\parameter_files\\%s\\%d\\%s\\%s\\" report year pmFirm pmName //(System.DateTime.Now.ToString("ddMMyyyy"))
Directory.CreateDirectory(path) |> ignore
let filename = sprintf "%s%s" path month
printfn "%s" filename
use fs = new FileStream(filename, FileMode.Create)
let xmlSerializer = XmlSerializer(typeof<reportGenerator>)
xmlSerializer.Serialize(fs,root)
fs.Close()
XmlWriterSettings has some options for formatting the output, so pass the output through XmlWriter.
You should be able to something like this (don't have FSI at hand right now, don't know if it compiles. :)
//use fs = new FileStream(filename, FileMode.Create)
let settings = new XmlWriterSettings();
settings.Indent <- true;
settings.NewLineChars <- "\n";
use w = XmlWriter.Create(filename, settings);
let xmlSerializer = XmlSerializer(typeof<reportGenerator>)
xmlSerializer.Serialize(w,root)
It's probably not the best solution, but you could try
// after your current code
let xmlString = File.ReadAllText filename
ignore( File.WriteAllText( filename , xmlString.Replace("\r","")))

Resources