سؤال

I'm trying to make a function that exports an XLSX file based on a template. I currently unzip the template file, go through all the XML files looking for the worksheets, and then do a global find-and-replace on the appropriate strings - placeholder_1, placeholder_2 and so on.

This does work but when you save the Excel file with placeholder_1 etc. it marks those cells as text cells, so in the output you get loads of "Number stored as string errors". One possible solution is to save them as numbers - 100001, 100002, etc. But that isn't very nice.

Another option would be to do that and then go into the worksheet XML and replace 10000 with placeholder_ so I have "strings stored as numbers" which is what I want. But that means you can't easily edit the template in Excel.

So does anyone know a way of storing a normal number cell in an XLSX file that actually contains text rather than a number?

(Yes I know this is somewhat hacky. If I had more time I would do a proper XML parser and everything, but I don't.)

هل كانت مفيدة؟

المحلول

In the XML file corresponding the the worksheet, a cell is an entity like this:

<c r="A2" t="n">
    <v>18.999</v>
</v>
  • Attribut r is the address of the cell in the worksheet.
  • Attribut t type of the value stored by the cell (n=numeric, s=string, b=boolean), 'n' is the default value..
  • Entity <v> contains the unformatted value in case of numeric or boolean. But, in case of a string, <v> contains the index value of the string stored in the file "xl/sharedStrings.xml" .

So your problem is to replace a combination such as :

file "xl/worksheets/sheet1.xml" :

<c r="A2" t="s">
    <v>29</v>
</c>

file "xl/sharedStrings.xml" :

<sst>
  ...
  <si><t>placeholder_1</t></si> // 29th entity
  ...
</sst>

with :

file "xl/worksheets/sheet1.xml" :

<c r="A2" t="n">
    <v>100001</v>
</c>

So in order to change the placeholder and the cell type, you have to :

  1. Search into "sharedStrings.xml" for the index of entity <si> where is placed your placeholder (the value of the index is not explicit in "sharedStrings.xml" ).
  2. Search into "sheet1.xml" for the <v> entity that contains this index.
  3. Replace the value of this <v> entity with the unformatted numerical value.
  4. Replace the attribute of its parent <c> entity with "n" (or delete attribute t="s").

The good news are :

  • You can leave unused shared string in "xl/sharedStrings.xml", this will not make an error.
  • You can apply a number format to your cell while it contains the string value placeholder_1. This number format will be kept and applied to the number when you'll change the cell type.

If you have the pleasure to work with PHP, there is a nice library call OpenTBS that provides the feature of replacing textual placeholders in Excel worksheets and change the cell type if needed. OpenTBS is a plug-in for the TinyButStrong template engine for working with Ms Office and LibreOffice.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top