How can I get the meta-information of a bookmark?

Another possibility is:

  1. we use Aspose to convert Docx File into PDF File, we have tested this function of Aspose and we are satisifed with the result.
  2. we use Aspose to read the x/y-position, width, height and page number of signature from the PDF File instead of the DocxFile.
  3. We send the PDF File and the layout information of signature to AdobeSign/DocuSign.

So, if this way works fine, then we can also say that Aspose passed this test. Now the question is: is it possible for Aspose to read such layout information from a PDF file?

@zwei No, Aspose.Words for Java does not support PDF as input document format. But you can use the same code to determine coordinates and then save your input document as PDF.

OK, then we will organize such a test soon:

  1. use Aspose to read Layout info of Signatures from Docx
  2. use Aspose to convert the Docx into PDF
  3. send Signature Layout Infos and the PDF File to AdobeSign/DocuSign

Actually we must guarantee that Aspose can work with AdobeSign/DocuSign together, that is a mission critical requirement of my company. After the test, I will post the test results here.

@zwei Sure we will wait for your inputs.

AdobeSign and DocuSign both have definitively no bugs in this feature. Currently we use a VBA component to read such layout information directly from MS-Word, then pass the docx file and layout information to AdobeSign/DocuSign Cloud API. It works always, never got any problem.

Aspose is the first case that fail this test.

@zwei Unfortunately, I do not see defects in Aspose.Words when process your documents. The coordinates returned by Aspose.Words fully correspond the coordinates of signatures placeholders in your document, that was proven by placing red rectangles in the document.

Such coordination generated by Aspose.Words, then consumed by Aspose.Words, at last Aspose give the result which is correct.

But now, such coordination generated by Aspose.Words would be consumed by AdobeSign/DocuSign, at last AS/DS give the result, and this result must be acceptable. That is mission critical for me.

@zwei MS Word documents are flow documents and do not contain any information about document layout. Aspose.Words uses it own layout engine to build document layout and get layout information. You have already checked conversion of the document to PDF using Aspose.Words and the result corresponds to what you see in MS Word. So Aspose.Words layout engine properly determines coordinates and size of objects in the document.

1 Like

PDF Generation, Screenshot Generation, such Aspose functionalities have passed our tests already.

But now, the capability of working with AdobeSign/DocuSign together is mission critical for my company.

Currently we use such a way:

  1. use Java to call Office VBA, then obtain the layout info of signatures
  2. send such layout info and the docx file to AdobeSign/DocuSign Cloud
  3. AdobeSign/DocuSign give the final result.

This feature is mission critical
 Such a way always works, never failed. If Aspose could pass this test, then our manage will be very likely to purchase Aspose.Words License.

@zwei Aspose.Words returns absolute coordinates of objects on a page, I suppose your Office VBA code does the same. Have you tested the same documents with Aspose.Words and VBA? What is the difference in coordinates? Could you please provide your VBA code for getting layout information here? We ill check it and provide you information.
Unfortunately, as I have mentioned, I do not see any issues with coordinates returned by Aspose.Words.

For example, for this test file, AndyField2.docx (494,9 KB)

There are two bookmarks in this file, they are “SIGN_Geschaeftsfuehrer” and “SIGN_Bereichsleiter”.

Our VBA has such a result

Our VBA gives such positions back:
“SIGN_Geschaeftsfuehrer”, x=68, y=520
“SIGN_Bereichsleiter”, x= 305, y=520

Yet Aspose has such a result:
Bookmark name: SIGN_Geschaeftsfuehrer
Bookmark start page: 1
Bookmark end page: 1
Page:1 X=70.9000015258789; Y=556.8989868164062; Width=216.05001068115234; Height=67.5

Bookmark name: SIGN_Bereichsleiter
Bookmark start page: 1
Bookmark end page: 1
Page:1 X=311.8999938964844; Y=556.8989868164062; Width=216.05001831054688; Height=67.5

As you can see, the width and height are good, however the x- and y-position of Aspose have problem.

We send such coordinates and the docx file to DocuSign, and the result is so:

/** Auslesen der verwendeten Felder im Dokument (in Verwendungsreihenfolge, nur einmal je SchlĂŒssel). Das geht leider
 * nur ĂŒber Word (benutzt JCOM)
 * @param inBT Die Datei
 * @param convert Ersetzt die Eingabedatei durch ein PDF
 * @param inOutImageBookmarks zu befĂŒllende Liste von Image-Bookmarks
 * @param inOutNonImageBookmarks zu befĂŒllende Liste von Nicht-Image-Bookmarks
 * @return Reihenfolgetreue Liste von Wertepaaren in Form von String-Arrays der LĂ€nge 2.
 */
private ArrayList<String[]> getWordDocPropertyFields( final BinaryTransfer inBT, boolean convert, ArrayList<String> mergeFields, ArrayList<String> inOutImageBookmarks, ArrayList<String> inOutNonImageBookmarks ) throws Exception
{
	String LOG_PREFIX = ".getWordDocPropertyFields() ";
	Log.log( getClass(), 6, LOG_PREFIX + "Reading Fields in Word Document!" );
	final File docfile = inBT.getFile();
	ArrayList<String[]> vpList = new ArrayList<String[]>();
	HashMap<String, String> valueMap = new HashMap<String, String>();
	// Word öffnen
	boolean success = false;
	File replacedDocfile = null;
//		try
//		{
		ComApplication app = ComApplication.getInstance( properties, ComApplication.WORD_APPLICATION );
		try
		{
		    ComObject wdApp = app.getComObject(); //ComObject.getInstance( properties, "Word.Application" );
			wdApp.put( "Visible", new Boolean( true ) ); // Word unsichtbar
			ComObject wdDocuments = (ComObject) wdApp.get( "Documents" );
	
			// Dokument öffnen
			Object[] arglist1 = new Object[1];
			arglist1[0] = docfile.getAbsolutePath();
			ComObject wdDocument = (ComObject) wdDocuments.method( "Open", arglist1 );
				
			// Neue Variante
			ComObject wdSections = (ComObject) wdDocument.get( "Sections" );
			Integer wdSectionCount = (Integer) wdSections.get( "Count" );

			HashSet<Integer> doneShapeIDs = new HashSet<Integer>(); //Marker, ob bereits verarbeitet
			for( int sec = 1; sec <= wdSectionCount; sec++ )
			{
				try
				{
					ComObject section = (ComObject) wdSections.method( "item", new Object[] { new Integer( sec ) } );
					Log.log( getClass(), 7, LOG_PREFIX + "got Section: " + sec );
	
					ComObject wdHeaders = (ComObject) section.get( "Headers" );
					gotInfosFromHeadersFooters( wdHeaders, vpList, valueMap, mergeFields, inOutImageBookmarks, inOutNonImageBookmarks, "Section: " + sec + ", Header: ", doneShapeIDs );
					ComObject wdFooters = (ComObject) section.get( "Footers" );
					gotInfosFromHeadersFooters( wdFooters, vpList, valueMap, mergeFields, inOutImageBookmarks, inOutNonImageBookmarks, "Section: " + sec + ", Footer: ", doneShapeIDs );
				}
				catch( Exception e )
				{
					Log.log( getClass(), 7, LOG_PREFIX + "ERROR getting Section: " + sec, e );
				}
			}
				
			ComObject storyranges = (ComObject) wdDocument.get( "StoryRanges" );
			for( int i = 1; i <= 17; i++ )
			{
				String reference = "Story Range: " + getTextForStoryRangeNumber( i );
				try
				{
					ComObject range = (ComObject) storyranges.method( "item", new Object[] { new Integer( i ) } ); // ggf. Exception = normal!
					Log.log( getClass(), 7, LOG_PREFIX + "got " + reference );
					int rangeCount = 1;
					while( range != null )
					{
						getInfosFromRange( range, vpList, valueMap, mergeFields, inOutImageBookmarks, inOutNonImageBookmarks,
							reference + ", Range: " + rangeCount++ );
						range = (ComObject) range.get( "NextStoryRange" );//StoryRanges sind listenartig bei Autoformen (Checkboxen...), i = 5
					}
				}
				catch( Exception e )
				{
					Log.log( getClass(), 7, LOG_PREFIX + "ERROR getting " + reference, e );
				}
			}
				
			Log.log( getClass(), 6, LOG_PREFIX + "Felder gelesen!" );
			success = true;
				
			if( convert )
			{
				replacedDocfile = convertToPDF( docfile, wdDocument );
			}
		}
		finally
		{
			final long timeout = Long.parseLong( this.properties.getProperty( PARAM_KILL_CLOSING_OFFICE_TIMEOUT, "10000" ) );
			app.closeApplication( success, timeout );
		}
			
		if( replacedDocfile != null )
		{
			inBT.setFile( replacedDocfile, true );
			inBT.isConverted = true;
		}
//		}
//		catch( Throwable e )
//		{
//			// Log.error( getClass(), LOG_PREFIX + e.getClass().getName() + " while ... :" + e.toString() );
//			Log.error( getClass(), LOG_PREFIX + "while ... : ", e );
//		}
	return vpList;
}

We use JCOM for the communication between our Java program and MS-Office, there are jcom.jar and jcom.dll, the package name of jcom is
package jp.ne.so_net.ga2.no_ji.jcom;

@zwei Thank you for additional information. It looks you are using Aspose.Words in evaluation mode and Aspose.Words injects an evaluation message at the top pf the document and the content is moved down. That is why there is such significant difference in Y coordinate. the licensed version of Aspose.Words returns correct coordinates:

Bookmark name: SIGN_Geschaeftsfuehrer
Bookmark start page: 1
Bookmark end page: 1
Page:1 X=70.9000015258789; Y=519.7830200195312; Width=216.05001831054688; Height=67.5
=============================
Bookmark name: SIGN_Bereichsleiter
Bookmark start page: 1
Bookmark end page: 1
Page:1 X=311.8999938964844; Y=519.7830200195312; Width=216.05001831054688; Height=67.5

You can request a free 30-days temporary license to test Aspose.Words on your side without evaluation version limitations.
Please see our documentation to learn more about evaluation version limitations and licensing:
https://docs.aspose.com/words/java/licensing/

1 Like

But the X- position of licensed edition Aspose has still deviation


@zwei I am sure the coordinates returned by Aspose.Words are correct. Please try pass the returned coordinates DocuSign and check the result.

Even with Evaluation Edition, we still manage to get the expected result now.

  1. we use Aspose to read layout info from docx
  2. we use Aspose to convert docx into PDF
  3. send layout info and PDF to AdobeSign/DocuSign (last failed tests all were Docx files instead of PDF files)

The result is good now!

image.png (66,8 KB)
image.png (94,1 KB)

OK, we will make further more tests, if all tests get good result, then we can say that Aspose pass our AdobeSign/DocuSign test.

@zwei It is perfect that you managed to achieve what you need. Please feel free to ask in case of any further issues. We will be glad to help you.

1 Like

Thank you very much, I believe that my company will be a customer of Aspose soon.

1 Like

There is NPE for this test file MatthiasBookmarkNPE.docx (37,0 KB)

If you open this test file in MS-Word, you will find there are only 4 bookmarks. However, doc.getRange().getBookmarks() gives 5 bookmarks, one of them has such a name “_GoBack”, and it has the same position as another existing bookmark.

The NPE occurs at this instruction for the bookmark “FIRMA_LOGO”:
enumerator.setCurrent(collector.getEntity(bk.getBookmarkStart()));

So is the Stacktrace:

java.lang.NullPointerException: Value cannot be null.
Parameter name: value
	at com.aspose.words.LayoutEnumerator.setCurrent(Unknown Source)
	at de.forcont.documentconverter.docx4j.service.AsposeHelper.SignatureFieldLayoutInfos(AsposeHelper.java:197)
	at de.forcont.documentconverter.docx4j.service.AsposeConverter.bookmarkNPETest(AsposeConverter.java:492)
	at de.forcont.documentconverter.docx4j.Docx4JTestMain.main(Docx4JTestMain.java:32)