XBA parsing and update with Excel VBA - excel

I'm trying to make an XML parser/updater through Excel VBA.
First of all, I have been going back and forth between Excel VBA and Python but it seemed like Excel VBA was a better option to me.
However, I am open to any method really so please let me know if anyone has a different suggestion that would work better.
So, what I want to do with this application.
Parse XML and note the information on Excel format
I need name and the value of each attributes along with the text value of each node
After getting the information in the Excel format, I want to be able to revise values and output back to the XML format
So, in a nutshell, I am really aiming for a XML editor I guess?
But I am stuck at a few issues from the startline.
Here's a brief implementation of the XML parsing portion:
'load xml document
Set xmlDoc = CreateObject("MSXML2.DOMDocument.6.0")
xmlDoc.async = False
xmlDoc.validateOnParse = False
xmlDoc.Load(xmlFilepath)
'get document elements
Set xmlDocElement = xmlDoc.DocumentElement
Debug.Print xmlDocElement.xml
For i = 0 To xmlDocElement.ChildNodes.Length - 1
Debug.Print xmlDocElement.ChildNodes(i).xml
For j = 0 To xmlDocElement.ChildNodes(i).Attributes.Length - 1
Debug.Print xmlDocElement.ChildNodes(i).Attributes.Item(j).Name
Debug.Print xmlDocElement.ChildNodes(i).Attributes.Item(j).Value
Next j
Debug.Print xmlDocElement.ChildNodes(i).Text
Next i
The above method works well more or less with an exception for two conditions, so far at least.
XML file cannot be loaded if the text includes &/>/<
XML file cannot be loaded if it includes more than 1 highest parent node.
Text including &/>/< sample:
<parenttag>
<childtag>I love mac&cheese</childtag>
</parenttag>
The answer I found online was quite conclusive:
Revise the text so that it does not use &/>/<.
But I cannot modify the text and need to keep the current format.
Any way to bypass this?
More than 1 highest parent node sample:
<parenttag>
<childtag>Text</childtag>
</parenttag>
<differenttag>
<childtag>Some other text</childtag>
</differenttag>
XML Load does not work with multiple parent tags in 1 XML file.
And again, I cannot modify the XML file content, so I need a way around the load error.
I also want to note that I have initially started this project
by reading XML file as a text and process line by line.
But, this did not work well with multi-line content
and thus trying to figure out a way to process XML file properly.
This question really includes multiple portions but I would really appreciate if I can get any help.

The issue is that any XML parser will only accept valid XML. And
<childtag>I love mac&cheese</childtag>
is just no valid XML. It should be encoded as
<childtag>I love mac&cheese</childtag>
So that is what you need to fix. You can only work with a standard (like XML standard) if everyone follow the XML standard rules and produces valid XML. Otherwise your code might look like XML but it is no XML (until it is valid).
Also multiple root elements is not allowed in XML. If it has multiple roots then it is no XML. So to get out of your issue the only thing you can do is fix those issues before loading the file into a parser. For example you can add a root tag to make your multiple parents become childs of that root:
<myroot>
<parenttag>
<childtag>Text</childtag>
</parenttag>
<differenttag>
<childtag>Some other text</childtag>
</differenttag>
</myroot>
And & that are not encoded yet need to be changed to & to make them valid.
The only other option is to write your own parser to parse that custom files which are not XML. But that will not be possible in 2 lines of code as you will need to develop a parser for your NON-XLM files.

Related

Blue Prism expression to get most recent file from folder

I am trying to write an expression on putting an attachment in the Outlook VBO and keep getting error that it cant find the file.
The file name is Investment Value_2022-12-13h12m37s45.xlsx bit everything after value will be different.
I have tried writing it as a wild card.
"C:\Users\AAPWP\Downloads\Investment*"
I tried filtering it into its own collection and getting it that way.
"File.File"
Trying to get the file path from a filtered collection.
"Attachment.Folder.Name"
Anybody having the same issue and any help would be appreciated.
Use 'Utility - File Mangement: Get Files' action to get all excel files
Loop through each file name and use 'Decision' action to check for file name pattern
Use formula - InStr([Files.Name], "Investment Value_") > 0
If True, then thats the file you need

Excel: Export to XML - With XML in cells

I'm trying to export a spreadsheet that has some XML in some of the cells of the table.
ID (column A): 23455
FACT (column B) (this code is copied & pasted from a sample cell - they don't all have this simplicity or structure):
"<div class=""fact"">
<p><strong>FACT.</strong> The closest star to our solar system is Alpha Centauri.</p>
</div>
"
I'd like to have XML like the following:
<record>
<ID>23455</ID>
<FACT><div class="fact"><p><strong>FACT.</strong> The closest star to our solar system is Alpha Centauri.</p></div></FACT>
</record>
This is complex enough that I doubt that Excel's native XML schema export will work (that thing is persnickety enough that I can't get it to work with simplest of data values).
My current thought is to write a Perl script, to read this as a CSV file and export XML. However, I've noticed that CSV does a poor job handling XML that's been "embedded" like this.
I'm hoping someone else might have a better suggestion for how to pull this information out.
Edit: Finally figured out the mistake I made with export. Can export and get the following:
<record>
<ID>23455</ID>
<FACT><div class="fact"><p><strong>FACT.</strong> The closest star to our solar system is Alpha Centauri.</p></div&gt
</FACT>
</record>
I think I can work with this...some regex and it might be good enough (looking for all < might put me at risk of killing a true less-than sign).
So I'm still open to suggestions
Just posting this as the answer...
If you export the column as text you can get the following:
<record>
<ID>23455</ID>
<FACT><div class="fact"><p><strong>FACT.</strong> The closest star to our solar system is Alpha Centauri.</p></div&gt
</FACT>
</record>
In an XML editor I did a find and replace to get all the tags using the following regex: s/<(\/?[\w\s="-_]+?)>/<$1>/
It's a bit dangerous if there are actual signs in the document, but you'd need a case where it was < /maybe and text with common tag symbols ="-_ > - possible but most equations are of the form X < Y < Z. Our content doesn't use <> all that much, so I can be fairly confident it won't catch the edge case.
I also "fixed" all the HTML (s/<b>/<b/>/ and s/<img (.*?)>/<img $1/>/) and checked parsing (theoretically an edge case would cause a parsing error).
And yes, I now have a doc in mixed DTD that will make all true XML peeps quake with horror, but I can work with it.

Skip element in BizTalk flat file assembly?

I've been tasked to map an input xml (actually an SAP idoc xml), and to generate a number of flat files. Each input xml may yield multiple output files (one output file per lot number), so I will be using xsl:key and the key() function in my mapping, based on the lot number
The thing is, the lot number itself will not be in the file itself, but the output file name needs to contain that lot number value.
So the question really is: can I map the lot number to the xml and have the flat file assembler skip it when it produces the file? Or is there another way the lot number can be applied as file name by the assembly without having it inside the file itself?
In your orchestration you can set a context property for each output message:
msgOutput(FILE.ReceivedFileName) = "DynamicStuff";
msgOutput then goes to the send shape.
In your send port you set the output file like this:
FixedStuff_%SourceFileName%.xml
The result:
FixedStuff_DynamicStuff.xml
If the value is not required in the message content, don't map it. That's it.
To insert at value in the file name, lot number in this case, you will need to promote that value to the FILE.ReceivedFileName Context Property. Then, you can use the %SourceFileName% Macro as part of the name setting in the Send Port. You can set FILE.ReceivedFileName by either Property Promotion or xpath() in an Orchestration.
Bonus: Sorting and Grouping in xslt is rather unwieldy, which is why I don't do that anymore. Instead, you can use SQL: BizTalk: Sorting and Grouping Flat File Data In SQL Instead of XSL

How can I search in PDF documents/PDX catalog in powershell

I have a vendor that supplies their documentation library as a series of PDF files (and some CHM files) and include a .PDX catalog also.
I want to write a powershell script to front end it (using either powershell forms, or hosting powershell in asp.net).
I'm in the early stages, I've worked out how to get document information from the PDF stream (the xmpmeta XML metadata block near the end of the PDF file - one of the few streams in the file that's in plaintext) which looks like this:
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:08:04
"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="
" xmlns:pdf="http://ns.adobe.com/pdf/1.3/"><pdf:Producer>GPL Ghostscript 8.64</pdf:Producer><pdf:Keywo
rds>86000056-413</pdf:Keywords></rdf:Description><rdf:Description rdf:about="" xmlns:xmp="http://ns.ad
obe.com/xap/1.0/"><xmp:ModifyDate>2011-03-03T17:38:34-05:00</xmp:ModifyDate><xmp:CreateDate>2011-01-28
T23:12:07+05:30</xmp:CreateDate><xmp:CreatorTool>PScript5.dll Version 5.2</xmp:CreatorTool><xmp:Metada
taDate>2011-03-03T17:38:34-05:00</xmp:MetadataDate></rdf:Description><rdf:Description rdf:about="" xml
ns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"><xmpMM:DocumentID>6cb2263d-2d61-11e0-0000-1390d57dcfcb</xmp
MM:DocumentID><xmpMM:InstanceID>uuid:1a0e68ba-14ad-4a03-b7a1-0a0e127b8753</xmpMM:InstanceID></rdf:Desc
ription><rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:format>applicati
on/pdf</dc:format><dc:title><rdf:Alt><rdf:li xml:lang="x-default">I/O Subsystem Programming Guide</rdf
:li></rdf:Alt></dc:title><dc:creator><rdf:Seq><rdf:li>Unisys Information Development</rdf:li></rdf:Seq
></dc:creator><dc:description><rdf:Alt><rdf:li xml:lang="x-default">ClearPath MCP 13.1,Application Dev
elopment,Administration,ClearPath MCP</rdf:li></rdf:Alt></dc:description></rdf:Description></rdf:RDF><
/x:xmpmeta>
using the following code (powershell v3, in v2 you need to select and expand the properties thus [string]$title = ($rdf.GetElementsByTagName('dc:title')| Select -expand Alt|Select -expand li)."#text"):
$file = ".\Downloads\68698703-007\PDF\86000056-413.pdf"
#determine what line in file the xmpmeta string starts
[int]$startln = (select-string -pattern '^<x:' $file).ToString().Split(":")[2]
#determine what line in file the xmpmeta string ends
[int]$endln = (select-string -pattern '^</x:' $file).ToString().Split(":")[2]
$startln--
#grab the xmpmeta and cast as type xml
[xml]$xmp = (gc $file)["$startln".."$endln"]
[xml]$rdf = $xmp.xmpmeta.InnerXml
#get title/creator/description element text
[string]$title = $rdf.GetElementsByTagName('dc:title').Alt.li."#text"
[string]$creator = $rdf.GetElementsByTagName('dc:creator').Alt.li."#text"
[string]$description = $rdf.GetElementsByTagName('dc:description').Alt.li."#text"
That's crucial because the filenames are in the format 12345678-123.pdf, the actual title is in the metadata itself, as well as document category etc.
So, I can produce a list of documents (displaying their proper titles, not the real filename) and allow them to be launched, but I also want to be able to search in all the documents using PDX file, but it's by no means plaintext!
I guess I could use one of a number of tools out there to convert each PDF into text, search it, repeat for each document and then return results for each document.
But, it strikes me that Adobe Reader already does that, so can I either start AcroRd32.exe with switches that will start the search, with search terms I've passed in to the AcroRd32 program, or can I use Adobe Search.API from within Powershell?
Any ideas specifically on automating load of the .PDX in Adobe Reader and firing off the search, or using adobe's API in powershell?
EDIT:
I can now launch acrobat from command line and search (so could mimic this in powershell) but the search only works when searching a PDF, not a PDX catalog. Both bring up the search pane, but only in a PDF document does the search field get populated and the search executed.
C:\Program Files (x86)\Adobe\Reader 10.0\Reader>AcroRd32.exe /A "search=trim" "P:\Doc Library\PDF\00_home.pdx"
Or
C:\Program Files (x86)\Adobe\Reader 10.0\Reader>AcroRd32.exe /A "search=trim" "P:\Doc Library\PDF\86000056-413.pdf"
Regards,
Graham
This is an old post, but be aware that the searching you do is potentially dangerous and that there is a better way to find the XMP metadata in a PDF file. XMP was designed specifically to be "findable" by text search. To that purpose it has a well defined begin and end code defined that is in there specifically so that you can extract the XMP data without having to parse the PDF format (or any other format the XMP metadata blob might be embedded in.
You can download the XMP specification here: http://www.adobe.com/devnet/xmp.html. Part 1 is the part where the explanation about XMP Packets explains how a text scanner can find the XMP packet with more accuracy.
Finally, PDF has an additional quirk that allows it to be incrementally updated. This might cause multiple XMP packets to appear in the file (where the last packet is normally the correct one). But annoyingly when the PDF is exported from applications like InDesign, images in the PDF (and other objects) might also have their own "object" XMP attached to it.
So consider where your files come from and how many strange things you might encounter and you want to provision for. But reading the XMP specification is not a bad idea for sure.

How to Create new Excel file out from seleniumRC result?

I'm creating a test case using selenium RC.
The General flow of the process is to get data from an Excel File.
Then run the SeleniumRC.
To get the result I place a printout command. All output is visible in the console. (using eclipse)
What I need to do next is to store all this data into a new Excel File. Can anyone help me on how to generate my output into an excel file.
Store the result in variables and then write them into the excel using the Java Excel API.
Use Jexcel API.This link may be useful to you.
http://r4r.co.in/java/apis/jexcel/
A simply way I will suggest is to append all the printout statements in a storage variable like string buffer(Java) with delimiters like | symbols at the end of each line and then write this information into a text file.(line by line by split with the help of | symbols)
If you want to store this information in excel you will have to use the Apache POI Project to write data into excel sheets.(http://poi.apache.org/)

Resources