Categories > OpenTBS with DOCX >

Replace Header in docx

The forum is closed. Please use Stack Overflow for submitting new questions. Use tags: tinybutstrong , opentbs
By: Chris
Date: 2013-08-06
Time: 16:11

Replace Header in docx

I need two different optional headers for a file, which I figured would be as simple as switching in a new XML file - as I'm already doing with the styles.xml file. (With much help from Sarah Kemp!)

Unfortunately it appears not. I'm using the very same code as I am for styles.xml, yet with no headers appearing, or error messages output. Do I need to treat headers differently, is anyone able to help?

My Code:
//Edit the styles file separately <--THIS WORKS
$TBS2 = new clsTinyButStrong;
$TBS2->LoadTemplate('templates/styles.xml');
$TBS2->Show(TBS_NOTHING);
$xmlStr = $TBS2->Source;

//Edit the header file separately <-- THIS DOESN'T
$TBS3 = new clsTinyButStrong;
if ($header == 'left') $TBS3->LoadTemplate('templates/header1.xml');
else $TBS3->LoadTemplate('header1.xml');
$TBS3->Show(TBS_NOTHING);
$xmlHeaderStr = $TBS3->Source;

//Then put the new styles file into the word zip
$TBS->Plugin(OPENTBS_REPLACEFILE, 'word/styles.xml', $xmlStr, $DataType=OPENTBS_STRING, $Compress=true);
$TBS->Plugin(OPENTBS_REPLACEFILE, 'word/header1.xml', $xmlHeaderStr, $DataType=OPENTBS_STRING, $Compress=true);
$TBS->Show(OPENTBS_DOWNLOAD, 'sample.docx');

I've checked that word/header1.xml, exists, and I'm getting no errors from the OPENTBS_REPLACEFILE. I've had a go at merging it as an OPENTBS_FILE instead of a string (although I'd be willing to admit I could be doing that wrong, there doesn't seem to be any doc for the syntax, so I kind of guessed.) On printing out $xmlHeaderStr - it still shows a list of tbs tags ([onshow.thisVar]) - is that what it should be? My styles.xml $xmlStr doesn't, yet there isn't any word-readable content in there.

Here's $xmlHeaderStr, as I'm not convinced this is as it should be.
[onshow.logo;ope=changepic;adjust=100%]DOCVARIABLE GMSD00056AA0136 \* MERGEFORMAT[onshow.var1][onshow.var2]: [onshow.var3] [onshow.var4]: [onshow.var5]
Help much appreciated as always!
By: Sarah Kemp
Date: 2013-08-06
Time: 17:40

Re: Replace Header in docx

Are you seeing the contents of $xmlHeaderStr included in the xml when you use $TBS->Show(OPENTBS_DEBUG_XML) instead of $TBS->Show(OPENTBS_DOWNLOAD, 'sample.docx')?

What do you mean when you say there isn't any word-readable content in $xmlStr?
By: Chris
Date: 2013-08-09
Time: 13:41

Re: Replace Header in docx

OPENTBS_DEBUG_XML shows the original header file being merged, (Although it makes no mention of my styles.xml file, which IS being merged.

W.r.t. word-readable content, I explained it badly. When I echo $xmlStr, I get an empty string. When I echo $xmlHeaderStr, I see the below.

[onshow.logo;ope=changepic;adjust=100%][onshow.var1][onshow.var2]: [onshow.var3] [onshow.var4]: [onshow.var5]

Both files contain onshow tags, although those in styles.xml I entered manually into the XML file, where as these in header1.xml, were entered through Microsoft word.


I've just tried `$TBS3->Show(TBS_OUTPUT);` - which gives me the same as above. So it looks like the template is loading, but the merge is failing???

I'll keep playing.
By: Chris
Date: 2013-08-09
Time: 15:50

Re: Replace Header in docx

--Probably best ignoring this message, and looking at the next one. Lots of slow and steady progress this afternoon--

Ok, so updates:

1. I think the MS Word spellchecker was disrupting my tags initially, I disabled that and manually messed with the XML to get my tags together properly. (If this WAS the issue, maybe it's worth noting in the manual somewhere?)
2. I then got an error as I was trying to use ope=changepic - which I believe is due to it being an opentbs method, where I was just loading this doc with standard TBS.
3. As such, I attempted to install the the opentbs_plugin to my new TBS class, yet I'm now stranded on the below error.
3.5. Because when using the openTBS library, I can now no longer do TBS3->Show(TBS_NOTHING) (I believe - is that right?). As such, I presume I instead have to save as a file, and replace it back in to my main doc as a file too? My guess at how to do this is below, although I haven't been able to come close to testing that as I can't get past the error at point 3...
4. Central rirectory (error below) was resolved by putting my xml file back inside a docx, and then loading it from that. Apparently you can't open an xml file directly with openTBS? DEBUG_XML now shows a mixture of xml and rubbish for TBS3 - but I think the rubbish may have something to do with changing the image? Now going to try going back to ope=changepic...

Any suggestions? (I've made another post specific to the error, as I see it all the time, and have no idea what it really means!) Thanks!

ERROR:
TinyButStrong Error OpenTBS Plugin: The End of Central Rirectory Record is not found. The process is ending, unless you set NoErr property to true.

NEXT ATTEMPT CODE:
$TBS2 = new clsTinyButStrong;
$TBS2->LoadTemplate('templates/styles.xml');
$TBS2->Show(TBS_NOTHING);
$xmlStr = $TBS2->Source;

//Edit the header file separately
$TBS3 = new clsTinyButStrong;
$TBS3->Plugin(TBS_INSTALL,OPENTBS_PLUGIN); // load the OpenTBS plugin
$TBS3->LoadTemplate('templates/headerLeft.docx#word/header1.xml',OPENTBS_ALREADY_XML);
$TBS3->PlugIn(OPENTBS_CHANGE_PICTURE, 'headerlogo', $logo);;
$TBS3->Show(OPENTBS_FILE, 'tmp.xml');

//Then put the new styles file into the word zip

$TBS->Plugin(OPENTBS_REPLACEFILE, 'word/styles.xml', $xmlStr, $DataType=OPENTBS_STRING, $Compress=true);
$TBS->Plugin(OPENTBS_REPLACEFILE, 'word/header1.xml', 'tmp.xml', $DataType=OPENTBS_FILE, $Compress=true);
By: Chris
Date: 2013-08-09
Time: 16:49

Re: Replace Header in docx

OK, hopefully the last message for the day. Been through a host of problems, and I'm now down to this.

header1.xml is merging correctly, I've found this from `$TBS3->Show(OPENTBS_DOWNLOAD)`. My last problem is that I can't get the xml string from this template ($tbsHeaderStr) to replace the relevent header file in $TBS. I get no errors, just the file doesn't replace.  `$TBS->PlugIn(OPENTBS_DEBUG_XML_CURRENT,TRUE);` still shows the header1 file from the original docx $TBS was built on.

Any ideas?

$TBS3 = new clsTinyButStrong;
$TBS3->Plugin(TBS_INSTALL,OPENTBS_PLUGIN); // load the OpenTBS plugin
$TBS3->LoadTemplate('templates/headerLeft.docx#word/header1.xml',OPENTBS_ALREADY_XML);
$TBS3->Show(OPENTBS_STRING);
$tbsHeaderStr = $TBS3->Source;

//Then put the new styles file into the word zip
$TBS->Plugin(OPENTBS_REPLACEFILE, 'word/header1.xml', $tbsHeaderStr, $DataType=OPENTBS_STRING, $Compress=true);
^^This line doesn't seem to have any effect,^^
$TBS->Plugin(OPENTBS_REPLACEFILE, 'word/styles.xml', $xmlStr, $DataType=OPENTBS_STRING, $Compress=true);

$TBS->PlugIn(OPENTBS_DEBUG_XML_CURRENT,TRUE);
$TBS->Show(OPENTBS_DOWNLOAD, 'sample.docx');
By: Sarah Kemp
Date: 2013-08-09
Time: 16:54

Re: Replace Header in docx

My only thought is this note in the OpenTBS manual about OPENTBS_REPLACEFILE: "Please note that any TBS merge on a file in the archive will cancel previous or future replacements."

Is it possible something is being merged in the original header1.xml which is causing it to override your replacement header1?
By: Chris
Date: 2013-08-12
Time: 17:51

Re: Replace Header in docx

I'd noticed this line, and wiped all my header accordingly. Looking into it further though (i.e. comparing to a fresh docx file's xml) my header hadn't deleted properly, and a header1.xml file (which I had presumed WAS the default, and had no TBS tags in at all) seemed to be taking priority over my replacement.

That is solved, and I am now 80% sure that my header file is being included (as I'm using ADDFILE instead, so there isn't a header1.xml file in the original template) - but I now appear to have some encoding issues, when I unzip my merged docx and look at header1.xml, it's unreadable. (as is the $OPENTBS_STRING I use to make it.)

I'm not sure how else to get around this, I'm stating the string I'm adding has data type OPENTBS_STRING - so I would have assumed the library should take care of the data conversion. I've tried it was $Compress=true and false, as I'm not entirely sure which it should be, neither with any joy.

I've also considered and tried saving a file from $TBS3, and then including that file into $TBS with OPENTBS_ADDFILE, yet I can't work out how to route to a file from an external source in this setting. The doc instructs me to 'include the inner path.' - I've tried 'tempHead.docx#word/header1.xml' as my filepath, but with no luck. (OPENTBS_FILEEXISTS tells me this doesn't exist, although I believe that only looks within the current docx, and I don't know if it's possible to break that.)

Here's my latest code, appreciate the help. As a side note - you'll see $TBS3->LoadTemplate is done with the flag OPENTBS_ALREADY_XML? This is as I'm also working with none-basic ascii chars, and using this option makes them render correctly when I try and just 'show' $TBS3. I don't think that affects the end result, as I've tried with and without.

$TBS2 = new clsTinyButStrong;
$TBS2->LoadTemplate('templates/styles.xml');
$TBS2->Show(TBS_NOTHING);
$xmlStr = $TBS2->Source;

//Edit the header file separately
$TBS3 = new clsTinyButStrong;
$TBS3->Plugin(TBS_INSTALL,OPENTBS_PLUGIN); // load the OpenTBS plugin
$TBS3->LoadTemplate('templates/headerLeft.docx#word/header1.xml',OPENTBS_ALREADY_XML);
$TBS3->Show(OPENTBS_STRING);
$tbsHeaderStr = $TBS3->Source;

$TBS->Plugin(OPENTBS_ADDFILE, 'word/header1.xml', $tbsHeaderStr, $DataType=OPENTBS_STRING, $Compress=true);
$TBS->Plugin(OPENTBS_REPLACEFILE, 'word/styles.xml', $xmlStr, $DataType=OPENTBS_STRING, $Compress=true);

$TBS->Show(OPENTBS_DOWNLOAD, 'sample.docx');


Thanks, as always. I know this may be a sense of deja vu, but I believe this will be my final issue! (For this project...)
By: Sarah Kemp
Date: 2013-08-12
Time: 18:04

Re: Replace Header in docx

My only suggestion is to take another look at the Load Template documentation: http://www.tinybutstrong.com/plugins/opentbs/tbs_plugin_opentbs.html#loadtemplate and see if anything stands out to you.

For instance, have you tried the OPENTBS_ALREADY_UTF8 instead of OPENTBS_ALREADY_XML for your "non-basic ascii chars"? There is also something there about using $TBS->LoadTemplate('document.odt#'); to disable automatic extension recognition, so perhaps by using $TBS3->LoadTemplate('templates/headerLeft.docx#word/header1.xml'), OpenTBS does not realize it is working with a .docx and fails to perform some necessary conversion or extraction? There is some talk of "special character conversion" performed based on extension recognition here: http://www.tinybutstrong.com/plugins/opentbs/tbs_plugin_opentbs.html#extension

Perhaps try the special command documented here: http://www.tinybutstrong.com/plugins/opentbs/tbs_plugin_opentbs.html#force_doctype

$TBS3->PlugIn(OPENTBS_FORCE_DOCTYPE, 'docx');
By: Chris
Date: 2013-08-14
Time: 18:09

Re: Replace Header in docx

An update: My encoding problems was with $TBS3->Show(OPENTBS_STRING) - this seems to only work for docx files, and as I'm working with an xml file in $TBS3, I needed to do $TBS3->Show(OPENTBS_FILE,'header2.xml'), to get the right string in $TBS3->Source.

Having figured this out though, adding a new header to a docx seems to be a virtual impossibility. When I add a file to a document with no header (as above), the file it added to the archive, but a load of the other docs need editing for relationships and that, so it has no effect. (I've tried adding all the new files in independently, but there appears to be all sorts of unique identifiers to prevent you doing this.) Whenever I try and replace the file, when I call 'Show' it seems to overwrite it again with the original. (I'm fairly sure the REPLACEFILE is happening, it returns 1, and errors when I try and replace something that doesn't exist.)

Spent a good three days working on this, which is time I can't really spare at the moment, so now planning instead to duplicate my entire document, and put the alternate headers in each one. More of a pain for template updates, but the only solution I can figure out, I've tried everything else I can come up with! Thanks for your help, regardless!
By: Sarah Kemp
Date: 2013-08-14
Time: 18:25

Re: Replace Header in docx

Sorry to hear that, perhaps Skrol will jump in with a miracle cure.

If all of your TBS tags are block triggered instead of show triggered then you could pretty easily set up a side script that runs through all of your various headers and automatically duplicates your document, adding each header and saving the templates rather than doing it manually (and dreading updates). Then when you make a change you would just have to run the side script to update all of your templates. This could always be a later improvement, if you don't have time now.
By: Skrol29
Date: 2013-08-21
Time: 01:11

Re: Replace Header in docx

Hi Chris, hi Sarah !

The problem is that when you are doing :
$TBS3->Show(OPENTBS_STRING);
then $TBS3->Source does not contains the source of the sub-file anymore but the binary source of the whole archive.

You can try to replace :
$TBS3->Show(OPENTBS_STRING);
$tbsHeaderStr = $TBS3->Source;
with :
$TBS3->Show(TBS_NOTHING);
$TBS3->LoadTemplate('#word/header1.xml');
$tbsHeaderStr = $TBS3->Source;

But the best solution according to me is to get the source of "header1.xml" from the archive without OpenTBS, then replace it in the current template, and then force to load it in the current template in order to have automatic filed merged.

OpenTBS includes the TbsZip class than can read zip archives. This is usefull but it may be changed in a new main version of OpenTBS.
For now, this should work (not tested):
$zip = new clsTbsZip();
$zip->Open('templates/headerLeft.docx');
$tbsHeaderStr = $zip->FileRead('word/header1.xml');
$zip->Close();

$TBS->Plugin(OPENTBS_REPLACEFILE, 'word/header1.xml', $tbsHeaderStr, OPENTBS_STRING);
$TBS->LoadTemplate('#word/header1.xml');


By: Chris
Date: 2013-08-22
Time: 18:58

Re: Replace Header in docx

Hi Skroll, thanks a lot for this, just to let you know I've clocked it, but am going away and pushed for time at the moment, hopefully I'll have a chance to have more of a play around in a couple of weeks time with it.
Cheers for your response though - I'll update with my result!
By: Chris
Date: 2013-09-10
Time: 16:29

Re: Replace Header in docx

OK! Onwards! So, I ran with both versions of the above code, neither with success. Focused on your preferred solution, and found that by using OPENTBS_ADDFILE, I could get the xml file into the docx alright, which prompted me to presume a problems with the OPENTBS_REPLACEFILE line.

So, I tried a manual OPENTBS_DELETEFILE followed by OPENTBS_ADDFILE, which leaves me instead with two header2.xml files in the directory. (I find this when I try to unzip, and Windows prompts me to rename one of them.

My conclusion? That this line isn't behaving as I'm expecting it to - it doesn't appear to be deleting the xml file.

$TBS->Plugin(OPENTBS_DELETEFILE, 'word/header2.xml');

The line returns 1 (true), and I believe it's finding the file ok, as I get different errors when the file can't be found. Is this potentially a bug, or am I doing something wrong still?

Cheers
By: Skrol29
Date: 2013-09-14
Time: 22:55

Re: Replace Header in docx

It may return true when you ask to delete the file, but OpenTBS rewrite the contents at the end because the file has been automatically loaded.
This is a border effect that I never met before.
It may also explain why the OPENTBS_REPLACEFILE didn't work neither.

Then this should work better:
$zip = new clsTbsZip();
$zip->Open('templates/headerLeft.docx');
$tbsHeaderStr = $zip->FileRead('word/header1.xml');
$zip->Close();

$TBS->LoadTemplate('#word/header1.xml'); // load the sub-file into $TBS->Source
$TBS->Source = $tbsHeaderStr; // Replace the content
$TBS->MergeFields('onload'); // merge [onload] fields and blocks


By: Chris
Date: 2013-09-18
Time: 20:11

Re: Replace Header in docx

So my contract for this work finished last week, but was determined to try and get this done, and you'll be pleased to know, the above worked!

One correction, for future Googlers, my version of OpenTBS didn't recognise MergeFields, I presume you meant MergeField Skrol? I just removed the line, as I was only using onshow fields anyway. =)

Skrol & Sarah - thank you both for your help with this one!
By: Skrol29
Date: 2013-09-18
Time: 22:30

Re: Replace Header in docx

Thanks for your feedback !