XPages - using POI 4 XPages and it errors on $ symbol exporting to Word/PDF - apache-poi

I am using the splendid POI4Xpages add-on for my Xpage. It does very well mapping the web page to the Word or PDF, but I have noticed it bombs when there is a dollar sign ($) within any of the fields on the Xpage/Notes document.
Right now, my workaround for users is to substitute USD in place of the $ symbol, but my users and I would like it to handle the $.
I enclosed the error dump below.
Suggestions for where to begin (and end) are much appreciated. Thank you in advance.
POI 4 XPages -> ERROR
--------------------------------------------------------------
Error : Error during Documentgeneration
POI LIB : 1.2.6.201312211419
StackTrace:
java.lang.IllegalArgumentException: Illegal group reference
at java.util.regex.Matcher.appendReplacement(Matcher.java:724)
at java.util.regex.Matcher.replaceAll(Matcher.java:824)
at java.lang.String.replaceAll(String.java:1591)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.processBookmarks2Run(DocumentProcessor.java:129)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.processBookmarks 2Paragraph(DocumentProcessor.java:118)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.processBookmarks 2Table(DocumentProcessor.java:110)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.processBookmarks 2Document(DocumentProcessor.java:84)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.processDocument( DocumentProcessor.java:193)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.generateNewFile( DocumentProcessor.java:143)
at biz.webgate.dominoext.poi.component.containers.UIDocument.processAjaxRequest( UIDocument.java:208)
at biz.webgate.dominoext.poi.component.actions.DocumentGenerationServerAction.in voke(DocumentGenerationServerAction.java:48)
at com.ibm.xsp.application.ActionListenerImpl.processAction(ActionListenerImpl.j ava:60)
at javax.faces.component.UICommand.broadcast(UICommand.java:324)
at com.ibm.xsp.component.UIEventHandler.broadcast(UIEventHandler.java:366)
at com.ibm.xsp.component.UIDataPanelBase.broadcast(UIDataPanelBase.java:400)
at com.ibm.xsp.extlib.component.layout.UIVarPublisherBase.broadcast(UIVarPublish erBase.java:185)
at com.ibm.xsp.component.UIViewRootEx.broadcast(UIViewRootEx.java:1535)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:307)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:428)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase .java:94)
at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:210)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:96)
at com.ibm.xsp.controller.FacesControllerImpl.execute(FacesControllerImpl.java:2 56)
at com.ibm.xsp.webapp.FacesServlet.serviceView(FacesServlet.java:228)
at com.ibm.xsp.webapp.FacesServletEx.serviceView(FacesServletEx.java:157)
at com.ibm.xsp.webapp.FacesServlet.service(FacesServlet.java:160)
at com.ibm.xsp.webapp.FacesServletEx.service(FacesServletEx.java:138)
at com.ibm.xsp.webapp.DesignerFacesServlet.service(DesignerFacesServlet.java:103 )
at com.ibm.designer.runtime.domino.adapter.ComponentModule.invokeServlet(Compone ntModule.java:576)
at com.ibm.domino.xsp.module.nsf.NSFComponentModule.invokeServlet(NSFComponentMo dule.java:1335)
at com.ibm.designer.runtime.domino.adapter.ComponentModule$AdapterInvoker.invoke Servlet(ComponentModule.java:853)
at com.ibm.designer.runtime.domino.adapter.ComponentModule$ServletInvoker.doServ ice(ComponentModule.java:796)
at com.ibm.designer.runtime.domino.adapter.ComponentModule.doService(ComponentMo dule.java:565)
at com.ibm.domino.xsp.module.nsf.NSFComponentModule.doService(NSFComponentModule .java:1319)
at com.ibm.domino.xsp.module.nsf.NSFService.doServiceInternal(NSFService.java:66 2)
at com.ibm.domino.xsp.module.nsf.NSFService.doService(NSFService.java:482)
at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.doService(LCDEnvironme nt.java:357)
at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.service(LCDEnvironment .java:313)
at com.ibm.domino.xsp.bridge.http.engine.XspCmdManager.service(XspCmdManager.jav a:272)

We had this same issue and basically did a hack like below to prefix a $ if we found a decimal. Hope this helps out.
function process(xwpfdocument){
try{
// Get POI Document
var x = xwpfdocument;
var tables:java.util.Iterator = x.getTablesIterator();
while(tables.hasNext()){
var t = tables.next();
var numRows = t.getNumberOfRows();
// Loop Through All Rows
if(numRows>0){
for(var row=0; row<numRows; row++){
var cellList:java.util.List = t.getRow(row).getTableCells();
var numCells = cellList.size();
// Loop through all Cells
for(var cell=0; cell<numCells; cell++){
var c = cellList.get(cell);
var paragraphs:java.util.List = c.getParagraphs();
// Loop through all Paragraphs
for(var para=0; para<paragraphs.size();para++){
var p = paragraphs.get(para);
var runs:java.util.List = p.getRuns();
// Loop through all Runs
for(var r=0;r<runs.size();r++){
var run = runs.get(r);
var txt=run.getText(0);
if(txt.indexOf("<NL>")>-1){
var newRun = p.createRun();
var newTxt = txt.split("<NL>");
for(var n=0; n<newTxt.length; n++){
// Add New Runs with Breaks
var prefix = "";
if(newTxt[n].indexOf(".")>-1){
prefix = "$";
}
newRun.setText(#Text(prefix+newTxt[n]));
newRun.addBreak();
}
//Delete old run
//p.removeRun(0);
} else { //added for cases with only one account
var newRun = p.createRun();
var prefix = "";
if(txt.indexOf("%")>-1) { //added so SS002, SS003, and SS004 keep the %, added from the Letter.getBookmarkAPR function, rather than prepending a $
//nothing required
} else if(txt.indexOf(".")>-1){
prefix = "$";
}
newRun.setText(#Text(prefix+txt));
}
//Delete old run
p.removeRun(0);
}
}
}
}
}
}
} catch(e){
// Write to Log
system.out.println(e.getLocalizedMessage());
}
//Done
return;
}

Christian Güdemann posted a new build that addressed the $ character in the middle of a text field issue.
http://www.webgate.biz/ftp/openntf/POI4XPages/snapshot/biz.webgate.dominoext.poi-1.3.0-SNAPSHOT.zip
Btw there is a mailinglist in place to be informed about development builds:
http://mm.wgcdev.ch/mailman/listinfo
Thank you for your help, Dwain and Christian!

Related

How get Lot/Serial number in Netsuite SuiteScript 2.0 for Inventory Adjustment Transaction?

I'm trying to get the serial numbers from a inventory adjustment in a user event script. The following code works very well for me when the amount to adjust is positive, but not when it is negative.
var invDet = transaction.getSublistSubrecord({sublistId:'inventory',
fieldId:'inventorydetail',
line:x});
for(var y = 0; y = invDet.getLineCount('inventoryassignment'); y++) {
var lotNumber = invDet.getSublistValue({sublistId:'inventoryassignment',
fieldId:'receiptinventorynumber',
line:y});
log.debug('lotNumber', lotNumber);
}
When adjust quantity is negative, receiptinvetorynumber is empty
I have tried using field id equal to 'issueinventorynumber' or 'binnunber' but the returned value is empty.
I found the following comment in a NetsuiteHub forum...
In 2.0 the getValue call returns the internal ID of the serial/lot number and the getText equivalent does not work. Depending on the exact logic you need to execute for the obtained numbers you might need to call a subsequent saved search to obtain the actual serial/lot numbers and not internal IDs (an 'inventorynumber' search will do the trick).
I tried this...
try{
var internalId = invdet.getSublistValue({sublistId:'inventoryassignment',fieldId:'internalid', line:y});
search.create({type:'inventorynumber', filters:[
['internalid', 'is', internalId]
], columns:['inventorynumber']}).run().each(function (result) {
binText = result.getValue('inventorynumber');
log.debug('binText', binText);
});
} catch(e) {
log.debug('Error', e.message);
throw e.message;
}
I am too inexperienced to make this work. I appreciate any help you can give me.
Thanks.
The challenge is that this area of the NetSuite API is not well documented. However, I pushed through it through trial and error and search hours.
var invDet = transaction.getSublistSubrecord({sublistId:'inventory',
fieldId:'inventorydetail',
line:x});
for(var y = 0; y = invDet.getLineCount('inventoryassignment'); y++) {
var Qty = invdet.getSublistValue({sublistId:'inventoryassignment',
fieldId:'quantity',
line:y});
var lotNumber = '';
if(Qty < 0)
{
var ivnNumId = nvdet.getSublistValue({sublistId:'inventoryassignment',
fieldId:'issueinventorynumber',
line:y});
if(ivnNumId !== '')
{
var invNum = record.load({type: 'inventorynumber',id:ivnNumId});
lotNumber = invNum.getValue({fieldId: 'inventorynumber'});
}
}
else
{
lotNumber = invdet.getSublistValue({sublistId:'inventoryassignment',
fieldId:'receiptinventorynumber',
line:y});
}
log.debug('lotNumber', lotNumber);
}
This information was very helpful in ss1.0
I hope it is useful to someone

How to manipulate a xml file and save it to disk?

I have two xml files with exactly same structure. The only difference is the inner text of the tags.
I want to replace the value in the first file with the corresponding value in the second file.
I have tried using the xml2json but the problem is it removed all the comments which I need in the final output.
So currently I am using xmldom.
I am able to manipulate the text but the changes are lost when I try to save the file to the disk.
var DOMParser = require("xmldom").DOMParser;
var serializer = new (require('xmldom')).XMLSerializer;
var fs = require('fs');
let firstXML = `<root>
<!--This is just a comment-->
<string name="one">SOMETHING</string>
</root>`
let secondXML = `<root>
<string name="one">ELSE</string>
</root>`
var firstDoc = new DOMParser().parseFromString(firstXML, "text/xml");
var secondDoc = new DOMParser().parseFromString(secondXML, "text/xml");
let elementsFirst = firstDoc.getElementsByTagName("string");
let elementsSecond = secondDoc.getElementsByTagName("string");
for(let i = 0; i < elementsFirst.length; ++i) {
let el = elementsFirst[i];
let name = el.getAttribute("name");
for(let j = 0; j < elementsSecond.length; ++j) {
if(name = elementsSecond[j].getAttribute("name")) {
el.firstChild.nodeValue = elementsSecond[j].firstChild.nodeValue;
break;
}
}
}
fs.writeFileSync("output.xml", serializer.serializeToString(firstDocs));
//Required output
`<root>
<!--This is just a comment-->
<string name="one">ELSE</string>
</root>`
Please don't ask me why, but if you replace this line
el.firstChild.nodeValue = elementsSecond[j].firstChild.nodeValue;
with this one
el.firstChild.data = elementsSecond[j].firstChild.nodeValue;
it will work as expected.
P.S. You have a typo in your if statement, you need ===, a single = will usually return true
Update: after finding the solution - I found out that it is duplicate of this one

Netsuite Email Merge Error (SSS_MERGER_ERROR_OCCURRED)

I'm creating a Scheduled SuiteScript in Netsuite that uses the 1.0 version of the API. The goal is to have the script run once per day to send our first time customers an email with their name (or company name) and other pre-formatted content using a Scriptable Email Template.
Once it is up and running, we are planning to extend it with additional functionality, but this is the base that we would like to have running before adding additional code.
The error message is:
SSS_MERGER_ERROR_OCCURRED - Merger error occurred: Unexpected error encountered during merging.
Everything goes smooth up until actually using .merge(). I've added the code below:
function thankyouletter() {
var searchresults = nlapiSearchRecord(null, 'customsearch127'); // minus: , filters
if (searchresults == null) {
response.write('Var searchresults is null.');
return;
} else {
nlapiLogExecution('DEBUG', 'START - Found search results', 'Starting iteration');
for (var i = 0; searchresults != null && i < searchresults.length; i++) {
var searchresult = searchresults[i];
var searchCols = searchresult.getAllColumns();
var internalid = searchresult.getId(); // Will be used after testing is finished
var emailMerger = nlapiCreateEmailMerger(38);
emailMerger.setEntity('customer', 24886); // Set for Testing
var mergeResult = emailMerger.merge(); // Fails and errors here
var emailSubject = mergeResult.getSubject();
var emailBody = mergeResult.getBody();
nlapiSendEmail(nlapiGetUser(), customerid, emailSubject, emailBody, null, null, null, null);
nlapiLogExecution('DEBUG', 'Merge Troubleshooting', 'Just after SendEmail');
}
}
var usageRemaining = context.getRemainingUsage();
nlapiLogExecution('DEBUG', 'usage left => ' + usageRemaining);
nlapiLogExecution('DEBUG', 'Script Finished.', 'Mission Complete');
}
I've removed some of the nlapiLogExecution lines for readability. If anything is confusing or additional info is needed, please let me know and I'll add/fix it.
I've dug through piles of Netsuite's documentation, SuiteAnswers, and web searches trying to find the solution, but the error message is pretty vague.
Any help is greatly appreciated! Thank you.
After further research, I found that the Freemarker Template had a syntax error, and that was causing the error.

Google Apps Script - remove spaces using .replace method

I'm trying to replace multiple whitespaces with single ones in a Google Doc with a script. But unfortunately the provided solution to this question isn't working for me. As you can see, I tried several alternatives but can not figure out how to do it right. Any ideas?
function searchAndReplace() {
var body = DocumentApp.getActiveDocument()
.getBody();
body.replaceText(/\s{2,}/,' ');
body.replaceText(/\s/g, " ") ;
body.replaceText("/\s/"," ");
body.replaceText('/\s{2,}/',' ');
}
Try:
function searchAndReplace() {
var body = DocumentApp.getActiveDocument().getBody();
body.editAsText().replaceText('\\s*', ' ');
}
UPDATE
One option is:
function getCorrections() {
var _getCorrections = 0,
text = DocumentApp.getActiveDocument().getBody().getText(),
regexp = /\s+/g,
matchesCorrections = text.match(regexp);
if (matchesCorrections) {
_getCorrections = matchesCorrections.reduce(function(previousValue,
currentValue) {
return previousValue + currentValue.length - 1;
}, 0);
}
return _getCorrections;
}

JSX/Photoshop: Selecting Initial History Snapshot - Looking for a shorter way

I have a piece of code that selects the initial state (snapshot) of the active document.
I wonder if there exist a short way to achieve the same goal.
Here is the actual script:
var myDoc = app.activeDocument.name;
var doc = app.activeDocument.historyStates.length;
alert("History States : " + doc);
function firstStep(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putName(cTID('SnpS'), myDoc);
desc1.putReference(cTID('null'), ref1);
executeAction(cTID('slct'), desc1, dialogMode);
alert("Selected Initial State");
};
firstStep();
Thanks in advance
Something along these lines should work for you:
docRef.activeHistoryState = docRef.historyStates.getByName('Snapshot 0');

Resources