Discussion:
General Support for Percentage Values?
Eliot Kimber
2018-08-15 20:40:53 UTC
Permalink
I need to extend the options for setting table widths.

Per the spec, a table's width can be an absolute measurement, a percentage value, or the keyword "auto".

Right now XWPFTable.setWidth() only takes an integer.

I'd like to extend it to take in addition a percentage value or the value "auto" (which I suppose conceptually is an enumeration with one possible value).

There doesn't seem to be a class that represents a percentage value (at least I couldn't find any declarations with the string "perc" in them.

Am I missing something for working with percentage values in the XWPF API?

Thanks,

E.

--
Eliot Kimber
http://contrext.com




---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org
Eliot Kimber
2018-08-15 22:39:50 UTC
Permalink
(This is in the context of setting the width on XWPFTable.)

I decided that the best (and simplest) approach would be to use strings to set the width value for "auto" and percentages, rather than creating a separate class that would just end up creating a percentage string anyway. This also matches the way the API is likely to be used, e.g., getting percentage value strings from some incoming source.

So I added a new setWidth(String widthValue) method to XWPFTable() which validates that it's a good value ("auto", an integer, or a percentage) and then if it's good, sets the value appropriately.

I also created a new method, getWidthDecimal(), to return the width value as a decimal (because percentages can be decimal values).

Using this test case:

XWPFDocument doc = new XWPFDocument();

XWPFTable xtab = doc.createTable();

assertEquals(0, xtab.getWidth());
assertEquals(STTblWidth.AUTO, xtab.getWidthType());

xtab.setWidth(1000);
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(1000, xtab.getWidth());

xtab.setWidth("auto");
assertEquals(STTblWidth.AUTO, xtab.getWidthType());
assertEquals(0, xtab.getWidth());
assertEquals(0.0, xtab.getWidthDecimal(), 0.01);

xtab.setWidth("999");
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(999, xtab.getWidth());

xtab.setWidth("50.5%");
assertEquals(STTblWidth.PCT, xtab.getWidthType());
assertEquals(50.5, xtab.getWidthDecimal(), 0.01);
assertEquals(50.5, xtab.getCTTbl().getTblPr().getTblW().xgetW().getBigDecimalValue().doubleValue(), 0.01);

Everything passes until the last test, where the value returned by getWidthDecimal() is 50.0, not 50.5.

It looks like the underlying CT class methods always set the value as an integer, even when using CTTblWidth.setBigDecimalValue():

} else if (widthValue.matches("[0-9]+(\\.[0-9]+)?%")) {
String numericPart = widthValue.substring(0, widthValue.length() - 1);
STDecimalNumber number = STDecimalNumber.Factory.newInstance();
number.setBigDecimalValue(new BigDecimal(numericPart));
ctWidth.xsetW(number);
ctWidth.setType(STTblWidth.PCT);

Debugging through this code I see that the @w:val attribute is "50" rather than "50.5" after the xsetW() method call.

This appears to be happening at a very low level.

Is there a way to fix this so that percentages can be decimals or have I misunderstood the specs and percentages should actually always be integers (although I'm pretty sure the spec allows fractional percentages).

Thanks,

Eliot
--
Eliot Kimber
http://contrext.com


On 8/15/18, 3:40 PM, "Eliot Kimber" <***@contrext.com> wrote:

I need to extend the options for setting table widths.

Per the spec, a table's width can be an absolute measurement, a percentage value, or the keyword "auto".

Right now XWPFTable.setWidth() only takes an integer.

I'd like to extend it to take in addition a percentage value or the value "auto" (which I suppose conceptually is an enumeration with one possible value).

There doesn't seem to be a class that represents a percentage value (at least I couldn't find any declarations with the string "perc" in them.

Am I missing something for working with percentage values in the XWPF API?

Thanks,

E.

--
Eliot Kimber
http://contrext.com




---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org






---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org
Eliot Kimber
2018-08-15 23:01:38 UTC
Permalink
If I manually set the @w:w value to the percentage string then I can get back the percentage and convert it to a double when the width type is set to percentage.

But I think there really needs to be a method on CTTblWidth that can return an STPercentage, parallel to xgetWidth(), which returns a BigDecimal.

Cheers,

E.

--
Eliot Kimber
http://contrext.com


On 8/15/18, 5:39 PM, "Eliot Kimber" <***@contrext.com> wrote:

(This is in the context of setting the width on XWPFTable.)

I decided that the best (and simplest) approach would be to use strings to set the width value for "auto" and percentages, rather than creating a separate class that would just end up creating a percentage string anyway. This also matches the way the API is likely to be used, e.g., getting percentage value strings from some incoming source.

So I added a new setWidth(String widthValue) method to XWPFTable() which validates that it's a good value ("auto", an integer, or a percentage) and then if it's good, sets the value appropriately.

I also created a new method, getWidthDecimal(), to return the width value as a decimal (because percentages can be decimal values).

Using this test case:

XWPFDocument doc = new XWPFDocument();

XWPFTable xtab = doc.createTable();

assertEquals(0, xtab.getWidth());
assertEquals(STTblWidth.AUTO, xtab.getWidthType());

xtab.setWidth(1000);
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(1000, xtab.getWidth());

xtab.setWidth("auto");
assertEquals(STTblWidth.AUTO, xtab.getWidthType());
assertEquals(0, xtab.getWidth());
assertEquals(0.0, xtab.getWidthDecimal(), 0.01);

xtab.setWidth("999");
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(999, xtab.getWidth());

xtab.setWidth("50.5%");
assertEquals(STTblWidth.PCT, xtab.getWidthType());
assertEquals(50.5, xtab.getWidthDecimal(), 0.01);
assertEquals(50.5, xtab.getCTTbl().getTblPr().getTblW().xgetW().getBigDecimalValue().doubleValue(), 0.01);

Everything passes until the last test, where the value returned by getWidthDecimal() is 50.0, not 50.5.

It looks like the underlying CT class methods always set the value as an integer, even when using CTTblWidth.setBigDecimalValue():

} else if (widthValue.matches("[0-9]+(\\.[0-9]+)?%")) {
String numericPart = widthValue.substring(0, widthValue.length() - 1);
STDecimalNumber number = STDecimalNumber.Factory.newInstance();
number.setBigDecimalValue(new BigDecimal(numericPart));
ctWidth.xsetW(number);
ctWidth.setType(STTblWidth.PCT);

Debugging through this code I see that the @w:val attribute is "50" rather than "50.5" after the xsetW() method call.

This appears to be happening at a very low level.

Is there a way to fix this so that percentages can be decimals or have I misunderstood the specs and percentages should actually always be integers (although I'm pretty sure the spec allows fractional percentages).

Thanks,

Eliot
--
Eliot Kimber
http://contrext.com


On 8/15/18, 3:40 PM, "Eliot Kimber" <***@contrext.com> wrote:

I need to extend the options for setting table widths.

Per the spec, a table's width can be an absolute measurement, a percentage value, or the keyword "auto".

Right now XWPFTable.setWidth() only takes an integer.

I'd like to extend it to take in addition a percentage value or the value "auto" (which I suppose conceptually is an enumeration with one possible value).

There doesn't seem to be a class that represents a percentage value (at least I couldn't find any declarations with the string "perc" in them.

Am I missing something for working with percentage values in the XWPF API?

Thanks,

E.

--
Eliot Kimber
http://contrext.com




---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org






---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org






---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org
pj.fanning
2018-08-16 07:09:07 UTC
Permalink
How about adding `void setWidthType(TableWidthType widthType)` and
`TableWidthType getWidthType()`?

TableWidthType would be a new Enum Type that supports the values on
STTblWidth.Enum.

NIL, PCT, DXA, AUTO

We don't like to expose the XMLBeans generated classes in our public API.



--
Sent from: http://apache-poi.1045710.n5.nabble.com/POI-User-f2280730.html

---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org
Murphy, Mark
2018-08-16 13:42:24 UTC
Permalink
According to the spec, w:val is always an integer value. What that integer represents depends on the w:type value. If w:type="auto" then it appears that w:val=0, or may even be ignored, but that will depend on the table width algorithm. I didn't look at that just now, it is very complex.

If w:type="dxa" then w:val is an integer that represents 20ths of a point. In that case I would take the value you specify in setCellWidth and multiply by 20 to get the integer for val (don't make the user provide val in 20ths of a point).

If w:type="pct" then w:val is an integer that represents 50ths of a point. In that case I would take the value specified in setCellWidth and multiply by 50 to get the integer for w:val (again don't make the user provide val in 50ths of a percent).

getCellWidth will have to honor these conventions as well. To retrieve cell width in points, you will have to divide w:val by 20, and to retrieve cell widths in percents, you will have to divide by 50. Note, there is no real way to convert between points and percent.

-----Original Message-----
From: Eliot Kimber [mailto:***@contrext.com]
Sent: Wednesday, August 15, 2018 7:02 PM
To: POI Users List <***@poi.apache.org>
Subject: Re: General Support for Percentage Values?

If I manually set the @w:w value to the percentage string then I can get back the percentage and convert it to a double when the width type is set to percentage.

But I think there really needs to be a method on CTTblWidth that can return an STPercentage, parallel to xgetWidth(), which returns a BigDecimal.

Cheers,

E.
--
Eliot Kimber
http://contrext.com


On 8/15/18, 5:39 PM, "Eliot Kimber" <***@contrext.com> wrote:

(This is in the context of setting the width on XWPFTable.)

I decided that the best (and simplest) approach would be to use strings to set the width value for "auto" and percentages, rather than creating a separate class that would just end up creating a percentage string anyway. This also matches the way the API is likely to be used, e.g., getting percentage value strings from some incoming source.

So I added a new setWidth(String widthValue) method to XWPFTable() which validates that it's a good value ("auto", an integer, or a percentage) and then if it's good, sets the value appropriately.

I also created a new method, getWidthDecimal(), to return the width value as a decimal (because percentages can be decimal values).

Using this test case:

XWPFDocument doc = new XWPFDocument();

XWPFTable xtab = doc.createTable();

assertEquals(0, xtab.getWidth());
assertEquals(STTblWidth.AUTO, xtab.getWidthType());

xtab.setWidth(1000);
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(1000, xtab.getWidth());

xtab.setWidth("auto");
assertEquals(STTblWidth.AUTO, xtab.getWidthType());
assertEquals(0, xtab.getWidth());
assertEquals(0.0, xtab.getWidthDecimal(), 0.01);

xtab.setWidth("999");
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(999, xtab.getWidth());

xtab.setWidth("50.5%");
assertEquals(STTblWidth.PCT, xtab.getWidthType());
assertEquals(50.5, xtab.getWidthDecimal(), 0.01);
assertEquals(50.5, xtab.getCTTbl().getTblPr().getTblW().xgetW().getBigDecimalValue().doubleValue(), 0.01);

Everything passes until the last test, where the value returned by getWidthDecimal() is 50.0, not 50.5.

It looks like the underlying CT class methods always set the value as an integer, even when using CTTblWidth.setBigDecimalValue():

} else if (widthValue.matches("[0-9]+(\\.[0-9]+)?%")) {
String numericPart = widthValue.substring(0, widthValue.length() - 1);
STDecimalNumber number = STDecimalNumber.Factory.newInstance();
number.setBigDecimalValue(new BigDecimal(numericPart));
ctWidth.xsetW(number);
ctWidth.setType(STTblWidth.PCT);

Debugging through this code I see that the @w:val attribute is "50" rather than "50.5" after the xsetW() method call.

This appears to be happening at a very low level.

Is there a way to fix this so that percentages can be decimals or have I misunderstood the specs and percentages should actually always be integers (although I'm pretty sure the spec allows fractional percentages).

Thanks,

Eliot
--
Eliot Kimber
http://contrext.com


On 8/15/18, 3:40 PM, "Eliot Kimber" <***@contrext.com> wrote:

I need to extend the options for setting table widths.

Per the spec, a table's width can be an absolute measurement, a percentage value, or the keyword "auto".

Right now XWPFTable.setWidth() only takes an integer.

I'd like to extend it to take in addition a percentage value or the value "auto" (which I suppose conceptually is an enumeration with one possible value).

There doesn't seem to be a class that represents a percentage value (at least I couldn't find any declarations with the string "perc" in them.

Am I missing something for working with percentage values in the XWPF API?

Thanks,

E.

--
Eliot Kimber
http://contrext.com




---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org






---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org






---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org For additional commands, e-mail: user-***@poi.apache.org

B�KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKCB��[��X��ܚX�KK[XZ[�\�\�][��X��ܚX�P�K�\X�K�ܙ�B��܈Y][ۘ[��[X[��K[XZ[
Eliot Kimber
2018-08-16 15:00:18 UTC
Permalink
I'm reading section 17.4.88 Table Measurement (CT_TblWidth), which shows this example:

<… w:type="pct" w:w="100%"/>

And which refers to 17.18.107 ST_MeasurementOrPercent (Measurement or Percentage Value) as the definition of the @w:w attribute.

It says it's a union of two types: ST_DecimalNumberOrPercent and ST_UniversalMeasure. ST_DecimalNumberOrPercent then says it's a union of ST_Percentage, 22.9.2.9 ST_Percentage (Percentage Value with Sign), which has this example:

<w:tcW w:type="pct" w:w="33.3%" />

I tried some experiements and if I modify the XML for my table to e.g.:

<w:tblW w:type="pct" w:w="50%"/>

And open it, Word correctly reflects the 50% width BUT when I save from Word the @w:w value is set to 2500 (50 * 50).

So clearly Word prefers to store things as integers, which makes sense, but it will read the % string value as defined in the spec.

I'm curious--what part of the spec are you reading that indicates that value is always an integer? I'm not doubting that it says that, but I didn't get to that part of the spec starting from the definitions for table width.

But this does suggest that my code that lets you set and get the table width (and the table cell widths, as you indicate, which I also need) is appropriate, in that it conforms to the spec, works with Word, and provides the convenience of allowing direct specific of the literal decimal percentage strings to .setWidth().

At the same time, there's no reason not to have the POI code do the percentage-to-integer conversion when it sets the @w:w value.

Cheers,

Eliot

--
Eliot Kimber
http://contrext.com


On 8/16/18, 8:42 AM, "Murphy, Mark" <***@metalexmfg.com> wrote:

According to the spec, w:val is always an integer value. What that integer represents depends on the w:type value. If w:type="auto" then it appears that w:val=0, or may even be ignored, but that will depend on the table width algorithm. I didn't look at that just now, it is very complex.

If w:type="dxa" then w:val is an integer that represents 20ths of a point. In that case I would take the value you specify in setCellWidth and multiply by 20 to get the integer for val (don't make the user provide val in 20ths of a point).

If w:type="pct" then w:val is an integer that represents 50ths of a point. In that case I would take the value specified in setCellWidth and multiply by 50 to get the integer for w:val (again don't make the user provide val in 50ths of a percent).

getCellWidth will have to honor these conventions as well. To retrieve cell width in points, you will have to divide w:val by 20, and to retrieve cell widths in percents, you will have to divide by 50. Note, there is no real way to convert between points and percent.

-----Original Message-----
From: Eliot Kimber [mailto:***@contrext.com]
Sent: Wednesday, August 15, 2018 7:02 PM
To: POI Users List <***@poi.apache.org>
Subject: Re: General Support for Percentage Values?

If I manually set the @w:w value to the percentage string then I can get back the percentage and convert it to a double when the width type is set to percentage.

But I think there really needs to be a method on CTTblWidth that can return an STPercentage, parallel to xgetWidth(), which returns a BigDecimal.

Cheers,

E.

--
Eliot Kimber
http://contrext.com


On 8/15/18, 5:39 PM, "Eliot Kimber" <***@contrext.com> wrote:

(This is in the context of setting the width on XWPFTable.)

I decided that the best (and simplest) approach would be to use strings to set the width value for "auto" and percentages, rather than creating a separate class that would just end up creating a percentage string anyway. This also matches the way the API is likely to be used, e.g., getting percentage value strings from some incoming source.

So I added a new setWidth(String widthValue) method to XWPFTable() which validates that it's a good value ("auto", an integer, or a percentage) and then if it's good, sets the value appropriately.

I also created a new method, getWidthDecimal(), to return the width value as a decimal (because percentages can be decimal values).

Using this test case:

XWPFDocument doc = new XWPFDocument();

XWPFTable xtab = doc.createTable();

assertEquals(0, xtab.getWidth());
assertEquals(STTblWidth.AUTO, xtab.getWidthType());

xtab.setWidth(1000);
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(1000, xtab.getWidth());

xtab.setWidth("auto");
assertEquals(STTblWidth.AUTO, xtab.getWidthType());
assertEquals(0, xtab.getWidth());
assertEquals(0.0, xtab.getWidthDecimal(), 0.01);

xtab.setWidth("999");
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(999, xtab.getWidth());

xtab.setWidth("50.5%");
assertEquals(STTblWidth.PCT, xtab.getWidthType());
assertEquals(50.5, xtab.getWidthDecimal(), 0.01);
assertEquals(50.5, xtab.getCTTbl().getTblPr().getTblW().xgetW().getBigDecimalValue().doubleValue(), 0.01);

Everything passes until the last test, where the value returned by getWidthDecimal() is 50.0, not 50.5.

It looks like the underlying CT class methods always set the value as an integer, even when using CTTblWidth.setBigDecimalValue():

} else if (widthValue.matches("[0-9]+(\\.[0-9]+)?%")) {
String numericPart = widthValue.substring(0, widthValue.length() - 1);
STDecimalNumber number = STDecimalNumber.Factory.newInstance();
number.setBigDecimalValue(new BigDecimal(numericPart));
ctWidth.xsetW(number);
ctWidth.setType(STTblWidth.PCT);

Debugging through this code I see that the @w:val attribute is "50" rather than "50.5" after the xsetW() method call.

This appears to be happening at a very low level.

Is there a way to fix this so that percentages can be decimals or have I misunderstood the specs and percentages should actually always be integers (although I'm pretty sure the spec allows fractional percentages).

Thanks,

Eliot
--
Eliot Kimber
http://contrext.com


On 8/15/18, 3:40 PM, "Eliot Kimber" <***@contrext.com> wrote:

I need to extend the options for setting table widths.

Per the spec, a table's width can be an absolute measurement, a percentage value, or the keyword "auto".

Right now XWPFTable.setWidth() only takes an integer.

I'd like to extend it to take in addition a percentage value or the value "auto" (which I suppose conceptually is an enumeration with one possible value).

There doesn't seem to be a class that represents a percentage value (at least I couldn't find any declarations with the string "perc" in them.

Am I missing something for working with percentage values in the XWPF API?

Thanks,

E.

--
Eliot Kimber
http://contrext.com




---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org






---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org






---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org For additional commands, e-mail: user-***@poi.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org
Murphy, Mark
2018-08-16 15:55:53 UTC
Permalink
Which version of the spec are you reading? We are using Version 1. Though we sometimes deal with later version artifacts, the CT and ST classes are all version 1.

-----Original Message-----
From: Eliot Kimber [mailto:***@contrext.com]
Sent: Thursday, August 16, 2018 11:00 AM
To: POI Users List <***@poi.apache.org>
Subject: Re: General Support for Percentage Values?

I'm reading section 17.4.88 Table Measurement (CT_TblWidth), which shows this example:

<… w:type="pct" w:w="100%"/>

And which refers to 17.18.107 ST_MeasurementOrPercent (Measurement or Percentage Value) as the definition of the @w:w attribute.

It says it's a union of two types: ST_DecimalNumberOrPercent and ST_UniversalMeasure. ST_DecimalNumberOrPercent then says it's a union of ST_Percentage, 22.9.2.9 ST_Percentage (Percentage Value with Sign), which has this example:

<w:tcW w:type="pct" w:w="33.3%" />

I tried some experiements and if I modify the XML for my table to e.g.:

<w:tblW w:type="pct" w:w="50%"/>

And open it, Word correctly reflects the 50% width BUT when I save from Word the @w:w value is set to 2500 (50 * 50).

So clearly Word prefers to store things as integers, which makes sense, but it will read the % string value as defined in the spec.

I'm curious--what part of the spec are you reading that indicates that value is always an integer? I'm not doubting that it says that, but I didn't get to that part of the spec starting from the definitions for table width.

But this does suggest that my code that lets you set and get the table width (and the table cell widths, as you indicate, which I also need) is appropriate, in that it conforms to the spec, works with Word, and provides the convenience of allowing direct specific of the literal decimal percentage strings to .setWidth().

At the same time, there's no reason not to have the POI code do the percentage-to-integer conversion when it sets the @w:w value.

Cheers,

Eliot
--
Eliot Kimber
http://contrext.com


On 8/16/18, 8:42 AM, "Murphy, Mark" <***@metalexmfg.com> wrote:

According to the spec, w:val is always an integer value. What that integer represents depends on the w:type value. If w:type="auto" then it appears that w:val=0, or may even be ignored, but that will depend on the table width algorithm. I didn't look at that just now, it is very complex.

If w:type="dxa" then w:val is an integer that represents 20ths of a point. In that case I would take the value you specify in setCellWidth and multiply by 20 to get the integer for val (don't make the user provide val in 20ths of a point).

If w:type="pct" then w:val is an integer that represents 50ths of a point. In that case I would take the value specified in setCellWidth and multiply by 50 to get the integer for w:val (again don't make the user provide val in 50ths of a percent).

getCellWidth will have to honor these conventions as well. To retrieve cell width in points, you will have to divide w:val by 20, and to retrieve cell widths in percents, you will have to divide by 50. Note, there is no real way to convert between points and percent.

-----Original Message-----
From: Eliot Kimber [mailto:***@contrext.com]
Sent: Wednesday, August 15, 2018 7:02 PM
To: POI Users List <***@poi.apache.org>
Subject: Re: General Support for Percentage Values?

If I manually set the @w:w value to the percentage string then I can get back the percentage and convert it to a double when the width type is set to percentage.

But I think there really needs to be a method on CTTblWidth that can return an STPercentage, parallel to xgetWidth(), which returns a BigDecimal.

Cheers,

E.

--
Eliot Kimber
http://contrext.com


On 8/15/18, 5:39 PM, "Eliot Kimber" <***@contrext.com> wrote:

(This is in the context of setting the width on XWPFTable.)

I decided that the best (and simplest) approach would be to use strings to set the width value for "auto" and percentages, rather than creating a separate class that would just end up creating a percentage string anyway. This also matches the way the API is likely to be used, e.g., getting percentage value strings from some incoming source.

So I added a new setWidth(String widthValue) method to XWPFTable() which validates that it's a good value ("auto", an integer, or a percentage) and then if it's good, sets the value appropriately.

I also created a new method, getWidthDecimal(), to return the width value as a decimal (because percentages can be decimal values).

Using this test case:

XWPFDocument doc = new XWPFDocument();

XWPFTable xtab = doc.createTable();

assertEquals(0, xtab.getWidth());
assertEquals(STTblWidth.AUTO, xtab.getWidthType());

xtab.setWidth(1000);
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(1000, xtab.getWidth());

xtab.setWidth("auto");
assertEquals(STTblWidth.AUTO, xtab.getWidthType());
assertEquals(0, xtab.getWidth());
assertEquals(0.0, xtab.getWidthDecimal(), 0.01);

xtab.setWidth("999");
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(999, xtab.getWidth());

xtab.setWidth("50.5%");
assertEquals(STTblWidth.PCT, xtab.getWidthType());
assertEquals(50.5, xtab.getWidthDecimal(), 0.01);
assertEquals(50.5, xtab.getCTTbl().getTblPr().getTblW().xgetW().getBigDecimalValue().doubleValue(), 0.01);

Everything passes until the last test, where the value returned by getWidthDecimal() is 50.0, not 50.5.

It looks like the underlying CT class methods always set the value as an integer, even when using CTTblWidth.setBigDecimalValue():

} else if (widthValue.matches("[0-9]+(\\.[0-9]+)?%")) {
String numericPart = widthValue.substring(0, widthValue.length() - 1);
STDecimalNumber number = STDecimalNumber.Factory.newInstance();
number.setBigDecimalValue(new BigDecimal(numericPart));
ctWidth.xsetW(number);
ctWidth.setType(STTblWidth.PCT);

Debugging through this code I see that the @w:val attribute is "50" rather than "50.5" after the xsetW() method call.

This appears to be happening at a very low level.

Is there a way to fix this so that percentages can be decimals or have I misunderstood the specs and percentages should actually always be integers (although I'm pretty sure the spec allows fractional percentages).

Thanks,

Eliot
--
Eliot Kimber
http://contrext.com


On 8/15/18, 3:40 PM, "Eliot Kimber" <***@contrext.com> wrote:

I need to extend the options for setting table widths.

Per the spec, a table's width can be an absolute measurement, a percentage value, or the keyword "auto".

Right now XWPFTable.setWidth() only takes an integer.

I'd like to extend it to take in addition a percentage value or the value "auto" (which I suppose conceptually is an enumeration with one possible value).

There doesn't seem to be a class that represents a percentage value (at least I couldn't find any declarations with the string "perc" in them.

Am I missing something for working with percentage values in the XWPF API?

Thanks,

E.

--
Eliot Kimber
http://contrext.com




---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org






---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org






---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org For additional commands, e-mail: user-***@poi.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org For additional commands, e-mail: user-***@poi.apache.org

Т���������������������������������������������������������������������ХF�V�7V'67&�&R�R���âW6W"�V�7V'67&�&T���6�R��&pФf�"FF�F����6����G2�R����
Eliot Kimber
2018-08-16 16:17:33 UTC
Permalink
I'm using ECMA-376 3rd Edition / June 2011, Office Open XML File Formats – Part 1

Although it looks like there's a 5th edition from 2015. I'll get that one:

https://www.ecma-international.org/publications/standards/Ecma-376.htm

Cheers,

E.
--
Eliot Kimber
http://contrext.com


On 8/16/18, 10:55 AM, "Murphy, Mark" <***@metalexmfg.com> wrote:

Which version of the spec are you reading? We are using Version 1. Though we sometimes deal with later version artifacts, the CT and ST classes are all version 1.

-----Original Message-----
From: Eliot Kimber [mailto:***@contrext.com]
Sent: Thursday, August 16, 2018 11:00 AM
To: POI Users List <***@poi.apache.org>
Subject: Re: General Support for Percentage Values?

I'm reading section 17.4.88 Table Measurement (CT_TblWidth), which shows this example:

<… w:type="pct" w:w="100%"/>

And which refers to 17.18.107 ST_MeasurementOrPercent (Measurement or Percentage Value) as the definition of the @w:w attribute.

It says it's a union of two types: ST_DecimalNumberOrPercent and ST_UniversalMeasure. ST_DecimalNumberOrPercent then says it's a union of ST_Percentage, 22.9.2.9 ST_Percentage (Percentage Value with Sign), which has this example:

<w:tcW w:type="pct" w:w="33.3%" />

I tried some experiements and if I modify the XML for my table to e.g.:

<w:tblW w:type="pct" w:w="50%"/>

And open it, Word correctly reflects the 50% width BUT when I save from Word the @w:w value is set to 2500 (50 * 50).

So clearly Word prefers to store things as integers, which makes sense, but it will read the % string value as defined in the spec.

I'm curious--what part of the spec are you reading that indicates that value is always an integer? I'm not doubting that it says that, but I didn't get to that part of the spec starting from the definitions for table width.

But this does suggest that my code that lets you set and get the table width (and the table cell widths, as you indicate, which I also need) is appropriate, in that it conforms to the spec, works with Word, and provides the convenience of allowing direct specific of the literal decimal percentage strings to .setWidth().

At the same time, there's no reason not to have the POI code do the percentage-to-integer conversion when it sets the @w:w value.

Cheers,

Eliot

--
Eliot Kimber
http://contrext.com


On 8/16/18, 8:42 AM, "Murphy, Mark" <***@metalexmfg.com> wrote:

According to the spec, w:val is always an integer value. What that integer represents depends on the w:type value. If w:type="auto" then it appears that w:val=0, or may even be ignored, but that will depend on the table width algorithm. I didn't look at that just now, it is very complex.

If w:type="dxa" then w:val is an integer that represents 20ths of a point. In that case I would take the value you specify in setCellWidth and multiply by 20 to get the integer for val (don't make the user provide val in 20ths of a point).

If w:type="pct" then w:val is an integer that represents 50ths of a point. In that case I would take the value specified in setCellWidth and multiply by 50 to get the integer for w:val (again don't make the user provide val in 50ths of a percent).

getCellWidth will have to honor these conventions as well. To retrieve cell width in points, you will have to divide w:val by 20, and to retrieve cell widths in percents, you will have to divide by 50. Note, there is no real way to convert between points and percent.

-----Original Message-----
From: Eliot Kimber [mailto:***@contrext.com]
Sent: Wednesday, August 15, 2018 7:02 PM
To: POI Users List <***@poi.apache.org>
Subject: Re: General Support for Percentage Values?

If I manually set the @w:w value to the percentage string then I can get back the percentage and convert it to a double when the width type is set to percentage.

But I think there really needs to be a method on CTTblWidth that can return an STPercentage, parallel to xgetWidth(), which returns a BigDecimal.

Cheers,

E.

--
Eliot Kimber
http://contrext.com


On 8/15/18, 5:39 PM, "Eliot Kimber" <***@contrext.com> wrote:

(This is in the context of setting the width on XWPFTable.)

I decided that the best (and simplest) approach would be to use strings to set the width value for "auto" and percentages, rather than creating a separate class that would just end up creating a percentage string anyway. This also matches the way the API is likely to be used, e.g., getting percentage value strings from some incoming source.

So I added a new setWidth(String widthValue) method to XWPFTable() which validates that it's a good value ("auto", an integer, or a percentage) and then if it's good, sets the value appropriately.

I also created a new method, getWidthDecimal(), to return the width value as a decimal (because percentages can be decimal values).

Using this test case:

XWPFDocument doc = new XWPFDocument();

XWPFTable xtab = doc.createTable();

assertEquals(0, xtab.getWidth());
assertEquals(STTblWidth.AUTO, xtab.getWidthType());

xtab.setWidth(1000);
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(1000, xtab.getWidth());

xtab.setWidth("auto");
assertEquals(STTblWidth.AUTO, xtab.getWidthType());
assertEquals(0, xtab.getWidth());
assertEquals(0.0, xtab.getWidthDecimal(), 0.01);

xtab.setWidth("999");
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(999, xtab.getWidth());

xtab.setWidth("50.5%");
assertEquals(STTblWidth.PCT, xtab.getWidthType());
assertEquals(50.5, xtab.getWidthDecimal(), 0.01);
assertEquals(50.5, xtab.getCTTbl().getTblPr().getTblW().xgetW().getBigDecimalValue().doubleValue(), 0.01);

Everything passes until the last test, where the value returned by getWidthDecimal() is 50.0, not 50.5.

It looks like the underlying CT class methods always set the value as an integer, even when using CTTblWidth.setBigDecimalValue():

} else if (widthValue.matches("[0-9]+(\\.[0-9]+)?%")) {
String numericPart = widthValue.substring(0, widthValue.length() - 1);
STDecimalNumber number = STDecimalNumber.Factory.newInstance();
number.setBigDecimalValue(new BigDecimal(numericPart));
ctWidth.xsetW(number);
ctWidth.setType(STTblWidth.PCT);

Debugging through this code I see that the @w:val attribute is "50" rather than "50.5" after the xsetW() method call.

This appears to be happening at a very low level.

Is there a way to fix this so that percentages can be decimals or have I misunderstood the specs and percentages should actually always be integers (although I'm pretty sure the spec allows fractional percentages).

Thanks,

Eliot
--
Eliot Kimber
http://contrext.com


On 8/15/18, 3:40 PM, "Eliot Kimber" <***@contrext.com> wrote:

I need to extend the options for setting table widths.

Per the spec, a table's width can be an absolute measurement, a percentage value, or the keyword "auto".

Right now XWPFTable.setWidth() only takes an integer.

I'd like to extend it to take in addition a percentage value or the value "auto" (which I suppose conceptually is an enumeration with one possible value).

There doesn't seem to be a class that represents a percentage value (at least I couldn't find any declarations with the string "perc" in them.

Am I missing something for working with percentage values in the XWPF API?

Thanks,

E.

--
Eliot Kimber
http://contrext.com




---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org






---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org






---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org For additional commands, e-mail: user-***@poi.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org For additional commands, e-mail: user-***@poi.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org
Mark Murphy
2018-08-16 16:25:31 UTC
Permalink
Use 1st edition, part 4. The CT classes were all generated from the 1st
edition schema.
I'm using ECMA-376 3rd Edition / June 2011, Office Open XML File Formats –
Part 1
https://www.ecma-international.org/publications/standards/Ecma-376.htm
Cheers,
E.
--
Eliot Kimber
http://contrext.com
Which version of the spec are you reading? We are using Version 1.
Though we sometimes deal with later version artifacts, the CT and ST
classes are all version 1.
-----Original Message-----
Sent: Thursday, August 16, 2018 11:00 AM
Subject: Re: General Support for Percentage Values?
<
 w:type="pct" w:w="100%"/>
And which refers to 17.18.107 ST_MeasurementOrPercent (Measurement or
It says it's a union of two types: ST_DecimalNumberOrPercent and
ST_UniversalMeasure. ST_DecimalNumberOrPercent then says it's a union of
ST_Percentage, 22.9.2.9 ST_Percentage (Percentage Value with Sign), which
<w:tcW w:type="pct" w:w="33.3%" />
<w:tblW w:type="pct" w:w="50%"/>
And open it, Word correctly reflects the 50% width BUT when I save
So clearly Word prefers to store things as integers, which makes
sense, but it will read the % string value as defined in the spec.
I'm curious--what part of the spec are you reading that indicates that
value is always an integer? I'm not doubting that it says that, but I
didn't get to that part of the spec starting from the definitions for table
width.
But this does suggest that my code that lets you set and get the table
width (and the table cell widths, as you indicate, which I also need) is
appropriate, in that it conforms to the spec, works with Word, and provides
the convenience of allowing direct specific of the literal decimal
percentage strings to .setWidth().
At the same time, there's no reason not to have the POI code do the
Cheers,
Eliot
--
Eliot Kimber
http://contrext.com
According to the spec, w:val is always an integer value. What that
integer represents depends on the w:type value. If w:type="auto" then it
appears that w:val=0, or may even be ignored, but that will depend on the
table width algorithm. I didn't look at that just now, it is very complex.
If w:type="dxa" then w:val is an integer that represents 20ths of
a point. In that case I would take the value you specify in setCellWidth
and multiply by 20 to get the integer for val (don't make the user provide
val in 20ths of a point).
If w:type="pct" then w:val is an integer that represents 50ths of
a point. In that case I would take the value specified in setCellWidth and
multiply by 50 to get the integer for w:val (again don't make the user
provide val in 50ths of a percent).
getCellWidth will have to honor these conventions as well. To
retrieve cell width in points, you will have to divide w:val by 20, and to
retrieve cell widths in percents, you will have to divide by 50. Note,
there is no real way to convert between points and percent.
-----Original Message-----
Sent: Wednesday, August 15, 2018 7:02 PM
Subject: Re: General Support for Percentage Values?
can get back the percentage and convert it to a double when the width type
is set to percentage.
But I think there really needs to be a method on CTTblWidth that
can return an STPercentage, parallel to xgetWidth(), which returns a
BigDecimal.
Cheers,
E.
--
Eliot Kimber
http://contrext.com
(This is in the context of setting the width on XWPFTable.)
I decided that the best (and simplest) approach would be to
use strings to set the width value for "auto" and percentages, rather than
creating a separate class that would just end up creating a percentage
string anyway. This also matches the way the API is likely to be used,
e.g., getting percentage value strings from some incoming source.
So I added a new setWidth(String widthValue) method to
XWPFTable() which validates that it's a good value ("auto", an integer, or
a percentage) and then if it's good, sets the value appropriately.
I also created a new method, getWidthDecimal(), to return the
width value as a decimal (because percentages can be decimal values).
XWPFDocument doc = new XWPFDocument();
XWPFTable xtab = doc.createTable();
assertEquals(0, xtab.getWidth());
assertEquals(STTblWidth.AUTO, xtab.getWidthType());
xtab.setWidth(1000);
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(1000, xtab.getWidth());
xtab.setWidth("auto");
assertEquals(STTblWidth.AUTO, xtab.getWidthType());
assertEquals(0, xtab.getWidth());
assertEquals(0.0, xtab.getWidthDecimal(), 0.01);
xtab.setWidth("999");
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(999, xtab.getWidth());
xtab.setWidth("50.5%");
assertEquals(STTblWidth.PCT, xtab.getWidthType());
assertEquals(50.5, xtab.getWidthDecimal(), 0.01);
assertEquals(50.5,
xtab.getCTTbl().getTblPr().getTblW().xgetW().getBigDecimalValue().doubleValue(),
0.01);
Everything passes until the last test, where the value
returned by getWidthDecimal() is 50.0, not 50.5.
It looks like the underlying CT class methods always set the
} else if (widthValue.matches("[0-9]+(\\.[0-9]+)?%")) {
String numericPart = widthValue.substring(0,
widthValue.length() - 1);
STDecimalNumber number =
STDecimalNumber.Factory.newInstance();
number.setBigDecimalValue(new
BigDecimal(numericPart));
ctWidth.xsetW(number);
ctWidth.setType(STTblWidth.PCT);
"50" rather than "50.5" after the xsetW() method call.
This appears to be happening at a very low level.
Is there a way to fix this so that percentages can be decimals
or have I misunderstood the specs and percentages should actually always be
integers (although I'm pretty sure the spec allows fractional percentages).
Thanks,
Eliot
--
Eliot Kimber
http://contrext.com
I need to extend the options for setting table widths.
Per the spec, a table's width can be an absolute
measurement, a percentage value, or the keyword "auto".
Right now XWPFTable.setWidth() only takes an integer.
I'd like to extend it to take in addition a percentage
value or the value "auto" (which I suppose conceptually is an enumeration
with one possible value).
There doesn't seem to be a class that represents a
percentage value (at least I couldn't find any declarations with the string
"perc" in them.
Am I missing something for working with percentage values in the XWPF API?
Thanks,
E.
--
Eliot Kimber
http://contrext.com
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
Eliot Kimber
2018-08-16 16:37:50 UTC
Permalink
Shouldn't we be reflecting the latest schemas?

Cheers,

E.

--
Eliot Kimber
http://contrext.com


On 8/16/18, 11:25 AM, "Mark Murphy" <***@gmail.com> wrote:

Use 1st edition, part 4. The CT classes were all generated from the 1st
edition schema.
Post by Eliot Kimber
I'm using ECMA-376 3rd Edition / June 2011, Office Open XML File Formats – Part 1
https://www.ecma-international.org/publications/standards/Ecma-376.htm
Cheers,
E.
--
Eliot Kimber
http://contrext.com
Which version of the spec are you reading? We are using Version 1.
Though we sometimes deal with later version artifacts, the CT and ST
classes are all version 1.
-----Original Message-----
Sent: Thursday, August 16, 2018 11:00 AM
Subject: Re: General Support for Percentage Values?
<… w:type="pct" w:w="100%"/>
And which refers to 17.18.107 ST_MeasurementOrPercent (Measurement or
It says it's a union of two types: ST_DecimalNumberOrPercent and
ST_UniversalMeasure. ST_DecimalNumberOrPercent then says it's a union of
ST_Percentage, 22.9.2.9 ST_Percentage (Percentage Value with Sign), which
<w:tcW w:type="pct" w:w="33.3%" />
<w:tblW w:type="pct" w:w="50%"/>
And open it, Word correctly reflects the 50% width BUT when I save
So clearly Word prefers to store things as integers, which makes
sense, but it will read the % string value as defined in the spec.
I'm curious--what part of the spec are you reading that indicates that
value is always an integer? I'm not doubting that it says that, but I
didn't get to that part of the spec starting from the definitions for table
width.
But this does suggest that my code that lets you set and get the table
width (and the table cell widths, as you indicate, which I also need) is
appropriate, in that it conforms to the spec, works with Word, and provides
the convenience of allowing direct specific of the literal decimal
percentage strings to .setWidth().
At the same time, there's no reason not to have the POI code do the
Cheers,
Eliot
--
Eliot Kimber
http://contrext.com
According to the spec, w:val is always an integer value. What that
integer represents depends on the w:type value. If w:type="auto" then it
appears that w:val=0, or may even be ignored, but that will depend on the
table width algorithm. I didn't look at that just now, it is very complex.
If w:type="dxa" then w:val is an integer that represents 20ths of
a point. In that case I would take the value you specify in setCellWidth
and multiply by 20 to get the integer for val (don't make the user provide
val in 20ths of a point).
If w:type="pct" then w:val is an integer that represents 50ths of
a point. In that case I would take the value specified in setCellWidth and
multiply by 50 to get the integer for w:val (again don't make the user
provide val in 50ths of a percent).
getCellWidth will have to honor these conventions as well. To
retrieve cell width in points, you will have to divide w:val by 20, and to
retrieve cell widths in percents, you will have to divide by 50. Note,
there is no real way to convert between points and percent.
-----Original Message-----
Sent: Wednesday, August 15, 2018 7:02 PM
Subject: Re: General Support for Percentage Values?
can get back the percentage and convert it to a double when the width type
is set to percentage.
But I think there really needs to be a method on CTTblWidth that
can return an STPercentage, parallel to xgetWidth(), which returns a
BigDecimal.
Cheers,
E.
--
Eliot Kimber
http://contrext.com
(This is in the context of setting the width on XWPFTable.)
I decided that the best (and simplest) approach would be to
use strings to set the width value for "auto" and percentages, rather than
creating a separate class that would just end up creating a percentage
string anyway. This also matches the way the API is likely to be used,
e.g., getting percentage value strings from some incoming source.
So I added a new setWidth(String widthValue) method to
XWPFTable() which validates that it's a good value ("auto", an integer, or
a percentage) and then if it's good, sets the value appropriately.
I also created a new method, getWidthDecimal(), to return the
width value as a decimal (because percentages can be decimal values).
XWPFDocument doc = new XWPFDocument();
XWPFTable xtab = doc.createTable();
assertEquals(0, xtab.getWidth());
assertEquals(STTblWidth.AUTO, xtab.getWidthType());
xtab.setWidth(1000);
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(1000, xtab.getWidth());
xtab.setWidth("auto");
assertEquals(STTblWidth.AUTO, xtab.getWidthType());
assertEquals(0, xtab.getWidth());
assertEquals(0.0, xtab.getWidthDecimal(), 0.01);
xtab.setWidth("999");
assertEquals(STTblWidth.DXA, xtab.getWidthType());
assertEquals(999, xtab.getWidth());
xtab.setWidth("50.5%");
assertEquals(STTblWidth.PCT, xtab.getWidthType());
assertEquals(50.5, xtab.getWidthDecimal(), 0.01);
assertEquals(50.5,
xtab.getCTTbl().getTblPr().getTblW().xgetW().getBigDecimalValue().doubleValue(),
0.01);
Everything passes until the last test, where the value
returned by getWidthDecimal() is 50.0, not 50.5.
It looks like the underlying CT class methods always set the
} else if (widthValue.matches("[0-9]+(\\.[0-9]+)?%")) {
String numericPart = widthValue.substring(0,
widthValue.length() - 1);
STDecimalNumber number =
STDecimalNumber.Factory.newInstance();
number.setBigDecimalValue(new
BigDecimal(numericPart));
ctWidth.xsetW(number);
ctWidth.setType(STTblWidth.PCT);
"50" rather than "50.5" after the xsetW() method call.
This appears to be happening at a very low level.
Is there a way to fix this so that percentages can be decimals
or have I misunderstood the specs and percentages should actually always be
integers (although I'm pretty sure the spec allows fractional percentages).
Thanks,
Eliot
--
Eliot Kimber
http://contrext.com
I need to extend the options for setting table widths.
Per the spec, a table's width can be an absolute
measurement, a percentage value, or the keyword "auto".
Right now XWPFTable.setWidth() only takes an integer.
I'd like to extend it to take in addition a percentage
value or the value "auto" (which I suppose conceptually is an enumeration
with one possible value).
There doesn't seem to be a class that represents a
percentage value (at least I couldn't find any declarations with the string
"perc" in them.
Am I missing something for working with percentage values in the XWPF API?
Thanks,
E.
--
Eliot Kimber
http://contrext.com
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org
Mark Murphy
2018-08-16 17:31:13 UTC
Permalink
There is a significant difference, and since the schemas are so tightly
integrated, that will be a lot of work. Someone tried at one time, and gave
up because it was too big a job. I am working on an alternative method that
will model the document in POJOs, and use readers and writers to read and
write the stored documents. This will remove that coupling, and allow us to
more easily upgrade the schema, but that is still in the beginning stage,
and is a real departure from how POI works.
Post by Eliot Kimber
Shouldn't we be reflecting the latest schemas?
Cheers,
E.
--
Eliot Kimber
http://contrext.com
Use 1st edition, part 4. The CT classes were all generated from the 1st
edition schema.
Post by Eliot Kimber
I'm using ECMA-376 3rd Edition / June 2011, Office Open XML File
Formats –
Post by Eliot Kimber
Part 1
Although it looks like there's a 5th edition from 2015. I'll get
https://www.ecma-international.org/publications/standards/Ecma-376.htm
Post by Eliot Kimber
Cheers,
E.
--
Eliot Kimber
http://contrext.com
Which version of the spec are you reading? We are using Version
1.
Post by Eliot Kimber
Though we sometimes deal with later version artifacts, the CT and ST
classes are all version 1.
-----Original Message-----
Sent: Thursday, August 16, 2018 11:00 AM
Subject: Re: General Support for Percentage Values?
I'm reading section 17.4.88 Table Measurement (CT_TblWidth),
which
Post by Eliot Kimber
<
 w:type="pct" w:w="100%"/>
And which refers to 17.18.107 ST_MeasurementOrPercent
(Measurement or
Post by Eliot Kimber
It says it's a union of two types: ST_DecimalNumberOrPercent and
ST_UniversalMeasure. ST_DecimalNumberOrPercent then says it's a
union of
Post by Eliot Kimber
ST_Percentage, 22.9.2.9 ST_Percentage (Percentage Value with Sign),
which
Post by Eliot Kimber
<w:tcW w:type="pct" w:w="33.3%" />
I tried some experiements and if I modify the XML for my table
<w:tblW w:type="pct" w:w="50%"/>
And open it, Word correctly reflects the 50% width BUT when I
save
Post by Eliot Kimber
So clearly Word prefers to store things as integers, which makes
sense, but it will read the % string value as defined in the spec.
I'm curious--what part of the spec are you reading that
indicates that
Post by Eliot Kimber
value is always an integer? I'm not doubting that it says that, but I
didn't get to that part of the spec starting from the definitions
for table
Post by Eliot Kimber
width.
But this does suggest that my code that lets you set and get the
table
Post by Eliot Kimber
width (and the table cell widths, as you indicate, which I also
need) is
Post by Eliot Kimber
appropriate, in that it conforms to the spec, works with Word, and
provides
Post by Eliot Kimber
the convenience of allowing direct specific of the literal decimal
percentage strings to .setWidth().
At the same time, there's no reason not to have the POI code do
the
Post by Eliot Kimber
Cheers,
Eliot
--
Eliot Kimber
http://contrext.com
According to the spec, w:val is always an integer value.
What that
Post by Eliot Kimber
integer represents depends on the w:type value. If w:type="auto"
then it
Post by Eliot Kimber
appears that w:val=0, or may even be ignored, but that will depend
on the
Post by Eliot Kimber
table width algorithm. I didn't look at that just now, it is very
complex.
Post by Eliot Kimber
If w:type="dxa" then w:val is an integer that represents
20ths of
Post by Eliot Kimber
a point. In that case I would take the value you specify in
setCellWidth
Post by Eliot Kimber
and multiply by 20 to get the integer for val (don't make the user
provide
Post by Eliot Kimber
val in 20ths of a point).
If w:type="pct" then w:val is an integer that represents
50ths of
Post by Eliot Kimber
a point. In that case I would take the value specified in
setCellWidth and
Post by Eliot Kimber
multiply by 50 to get the integer for w:val (again don't make the
user
Post by Eliot Kimber
provide val in 50ths of a percent).
getCellWidth will have to honor these conventions as well. To
retrieve cell width in points, you will have to divide w:val by 20,
and to
Post by Eliot Kimber
retrieve cell widths in percents, you will have to divide by 50.
Note,
Post by Eliot Kimber
there is no real way to convert between points and percent.
-----Original Message-----
Sent: Wednesday, August 15, 2018 7:02 PM
Subject: Re: General Support for Percentage Values?
then I
Post by Eliot Kimber
can get back the percentage and convert it to a double when the
width type
Post by Eliot Kimber
is set to percentage.
But I think there really needs to be a method on CTTblWidth
that
Post by Eliot Kimber
can return an STPercentage, parallel to xgetWidth(), which returns a
BigDecimal.
Cheers,
E.
--
Eliot Kimber
http://contrext.com
(This is in the context of setting the width on
XWPFTable.)
Post by Eliot Kimber
I decided that the best (and simplest) approach would be
to
Post by Eliot Kimber
use strings to set the width value for "auto" and percentages,
rather than
Post by Eliot Kimber
creating a separate class that would just end up creating a
percentage
Post by Eliot Kimber
string anyway. This also matches the way the API is likely to be
used,
Post by Eliot Kimber
e.g., getting percentage value strings from some incoming source.
So I added a new setWidth(String widthValue) method to
XWPFTable() which validates that it's a good value ("auto", an
integer, or
Post by Eliot Kimber
a percentage) and then if it's good, sets the value appropriately.
I also created a new method, getWidthDecimal(), to
return the
Post by Eliot Kimber
width value as a decimal (because percentages can be decimal values).
XWPFDocument doc = new XWPFDocument();
XWPFTable xtab = doc.createTable();
assertEquals(0, xtab.getWidth());
assertEquals(STTblWidth.AUTO,
xtab.getWidthType());
Post by Eliot Kimber
xtab.setWidth(1000);
assertEquals(STTblWidth.DXA,
xtab.getWidthType());
Post by Eliot Kimber
assertEquals(1000, xtab.getWidth());
xtab.setWidth("auto");
assertEquals(STTblWidth.AUTO,
xtab.getWidthType());
Post by Eliot Kimber
assertEquals(0, xtab.getWidth());
assertEquals(0.0, xtab.getWidthDecimal(), 0.01);
xtab.setWidth("999");
assertEquals(STTblWidth.DXA,
xtab.getWidthType());
Post by Eliot Kimber
assertEquals(999, xtab.getWidth());
xtab.setWidth("50.5%");
assertEquals(STTblWidth.PCT,
xtab.getWidthType());
Post by Eliot Kimber
assertEquals(50.5, xtab.getWidthDecimal(), 0.01);
assertEquals(50.5,
xtab.getCTTbl().getTblPr().getTblW().xgetW().getBigDecimalValue().doubleValue(),
Post by Eliot Kimber
0.01);
Everything passes until the last test, where the value
returned by getWidthDecimal() is 50.0, not 50.5.
It looks like the underlying CT class methods always set
the
Post by Eliot Kimber
} else if
(widthValue.matches("[0-9]+(\\.[0-9]+)?%")) {
Post by Eliot Kimber
String numericPart = widthValue.substring(0,
widthValue.length() - 1);
STDecimalNumber number =
STDecimalNumber.Factory.newInstance();
number.setBigDecimalValue(new
BigDecimal(numericPart));
ctWidth.xsetW(number);
ctWidth.setType(STTblWidth.PCT);
attribute is
Post by Eliot Kimber
"50" rather than "50.5" after the xsetW() method call.
This appears to be happening at a very low level.
Is there a way to fix this so that percentages can be
decimals
Post by Eliot Kimber
or have I misunderstood the specs and percentages should actually
always be
Post by Eliot Kimber
integers (although I'm pretty sure the spec allows fractional
percentages).
Post by Eliot Kimber
Thanks,
Eliot
--
Eliot Kimber
http://contrext.com
On 8/15/18, 3:40 PM, "Eliot Kimber" <
I need to extend the options for setting table
widths.
Post by Eliot Kimber
Per the spec, a table's width can be an absolute
measurement, a percentage value, or the keyword "auto".
Right now XWPFTable.setWidth() only takes an integer.
I'd like to extend it to take in addition a
percentage
Post by Eliot Kimber
value or the value "auto" (which I suppose conceptually is an
enumeration
Post by Eliot Kimber
with one possible value).
There doesn't seem to be a class that represents a
percentage value (at least I couldn't find any declarations with the
string
Post by Eliot Kimber
"perc" in them.
Am I missing something for working with percentage
values
Post by Eliot Kimber
in the XWPF API?
Thanks,
E.
--
Eliot Kimber
http://contrext.com
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
Post by Eliot Kimber
---------------------------------------------------------------------
---------------------------------------------------------------------
Eliot Kimber
2018-08-16 19:40:35 UTC
Permalink
Makes sense--I figured it was something like that.

Cheers,

E.

--
Eliot Kimber
http://contrext.com


On 8/16/18, 12:31 PM, "Mark Murphy" <***@gmail.com> wrote:

There is a significant difference, and since the schemas are so tightly
integrated, that will be a lot of work. Someone tried at one time, and gave
up because it was too big a job. I am working on an alternative method that
will model the document in POJOs, and use readers and writers to read and
write the stored documents. This will remove that coupling, and allow us to
more easily upgrade the schema, but that is still in the beginning stage,
and is a real departure from how POI works.
Post by Eliot Kimber
Shouldn't we be reflecting the latest schemas?
Cheers,
E.
--
Eliot Kimber
http://contrext.com
Use 1st edition, part 4. The CT classes were all generated from the 1st
edition schema.
Post by Eliot Kimber
I'm using ECMA-376 3rd Edition / June 2011, Office Open XML File
Formats –
Post by Eliot Kimber
Part 1
Although it looks like there's a 5th edition from 2015. I'll get
https://www.ecma-international.org/publications/standards/Ecma-376.htm
Post by Eliot Kimber
Cheers,
E.
--
Eliot Kimber
http://contrext.com
Which version of the spec are you reading? We are using Version
1.
Post by Eliot Kimber
Though we sometimes deal with later version artifacts, the CT and ST
classes are all version 1.
-----Original Message-----
Sent: Thursday, August 16, 2018 11:00 AM
Subject: Re: General Support for Percentage Values?
I'm reading section 17.4.88 Table Measurement (CT_TblWidth),
which
Post by Eliot Kimber
<… w:type="pct" w:w="100%"/>
And which refers to 17.18.107 ST_MeasurementOrPercent
(Measurement or
Post by Eliot Kimber
It says it's a union of two types: ST_DecimalNumberOrPercent and
ST_UniversalMeasure. ST_DecimalNumberOrPercent then says it's a
union of
Post by Eliot Kimber
ST_Percentage, 22.9.2.9 ST_Percentage (Percentage Value with Sign),
which
Post by Eliot Kimber
<w:tcW w:type="pct" w:w="33.3%" />
I tried some experiements and if I modify the XML for my table
<w:tblW w:type="pct" w:w="50%"/>
And open it, Word correctly reflects the 50% width BUT when I
save
Post by Eliot Kimber
So clearly Word prefers to store things as integers, which makes
sense, but it will read the % string value as defined in the spec.
I'm curious--what part of the spec are you reading that
indicates that
Post by Eliot Kimber
value is always an integer? I'm not doubting that it says that, but I
didn't get to that part of the spec starting from the definitions
for table
Post by Eliot Kimber
width.
But this does suggest that my code that lets you set and get the
table
Post by Eliot Kimber
width (and the table cell widths, as you indicate, which I also
need) is
Post by Eliot Kimber
appropriate, in that it conforms to the spec, works with Word, and
provides
Post by Eliot Kimber
the convenience of allowing direct specific of the literal decimal
percentage strings to .setWidth().
At the same time, there's no reason not to have the POI code do
the
Post by Eliot Kimber
Cheers,
Eliot
--
Eliot Kimber
http://contrext.com
According to the spec, w:val is always an integer value.
What that
Post by Eliot Kimber
integer represents depends on the w:type value. If w:type="auto"
then it
Post by Eliot Kimber
appears that w:val=0, or may even be ignored, but that will depend
on the
Post by Eliot Kimber
table width algorithm. I didn't look at that just now, it is very
complex.
Post by Eliot Kimber
If w:type="dxa" then w:val is an integer that represents
20ths of
Post by Eliot Kimber
a point. In that case I would take the value you specify in
setCellWidth
Post by Eliot Kimber
and multiply by 20 to get the integer for val (don't make the user
provide
Post by Eliot Kimber
val in 20ths of a point).
If w:type="pct" then w:val is an integer that represents
50ths of
Post by Eliot Kimber
a point. In that case I would take the value specified in
setCellWidth and
Post by Eliot Kimber
multiply by 50 to get the integer for w:val (again don't make the
user
Post by Eliot Kimber
provide val in 50ths of a percent).
getCellWidth will have to honor these conventions as well. To
retrieve cell width in points, you will have to divide w:val by 20,
and to
Post by Eliot Kimber
retrieve cell widths in percents, you will have to divide by 50.
Note,
Post by Eliot Kimber
there is no real way to convert between points and percent.
-----Original Message-----
Sent: Wednesday, August 15, 2018 7:02 PM
Subject: Re: General Support for Percentage Values?
then I
Post by Eliot Kimber
can get back the percentage and convert it to a double when the
width type
Post by Eliot Kimber
is set to percentage.
But I think there really needs to be a method on CTTblWidth
that
Post by Eliot Kimber
can return an STPercentage, parallel to xgetWidth(), which returns a
BigDecimal.
Cheers,
E.
--
Eliot Kimber
http://contrext.com
(This is in the context of setting the width on
XWPFTable.)
Post by Eliot Kimber
I decided that the best (and simplest) approach would be
to
Post by Eliot Kimber
use strings to set the width value for "auto" and percentages,
rather than
Post by Eliot Kimber
creating a separate class that would just end up creating a
percentage
Post by Eliot Kimber
string anyway. This also matches the way the API is likely to be
used,
Post by Eliot Kimber
e.g., getting percentage value strings from some incoming source.
So I added a new setWidth(String widthValue) method to
XWPFTable() which validates that it's a good value ("auto", an
integer, or
Post by Eliot Kimber
a percentage) and then if it's good, sets the value appropriately.
I also created a new method, getWidthDecimal(), to
return the
Post by Eliot Kimber
width value as a decimal (because percentages can be decimal values).
XWPFDocument doc = new XWPFDocument();
XWPFTable xtab = doc.createTable();
assertEquals(0, xtab.getWidth());
assertEquals(STTblWidth.AUTO,
xtab.getWidthType());
Post by Eliot Kimber
xtab.setWidth(1000);
assertEquals(STTblWidth.DXA,
xtab.getWidthType());
Post by Eliot Kimber
assertEquals(1000, xtab.getWidth());
xtab.setWidth("auto");
assertEquals(STTblWidth.AUTO,
xtab.getWidthType());
Post by Eliot Kimber
assertEquals(0, xtab.getWidth());
assertEquals(0.0, xtab.getWidthDecimal(), 0.01);
xtab.setWidth("999");
assertEquals(STTblWidth.DXA,
xtab.getWidthType());
Post by Eliot Kimber
assertEquals(999, xtab.getWidth());
xtab.setWidth("50.5%");
assertEquals(STTblWidth.PCT,
xtab.getWidthType());
Post by Eliot Kimber
assertEquals(50.5, xtab.getWidthDecimal(), 0.01);
assertEquals(50.5,
xtab.getCTTbl().getTblPr().getTblW().xgetW().getBigDecimalValue().doubleValue(),
Post by Eliot Kimber
0.01);
Everything passes until the last test, where the value
returned by getWidthDecimal() is 50.0, not 50.5.
It looks like the underlying CT class methods always set
the
Post by Eliot Kimber
} else if
(widthValue.matches("[0-9]+(\\.[0-9]+)?%")) {
Post by Eliot Kimber
String numericPart = widthValue.substring(0,
widthValue.length() - 1);
STDecimalNumber number =
STDecimalNumber.Factory.newInstance();
number.setBigDecimalValue(new
BigDecimal(numericPart));
ctWidth.xsetW(number);
ctWidth.setType(STTblWidth.PCT);
attribute is
Post by Eliot Kimber
"50" rather than "50.5" after the xsetW() method call.
This appears to be happening at a very low level.
Is there a way to fix this so that percentages can be
decimals
Post by Eliot Kimber
or have I misunderstood the specs and percentages should actually
always be
Post by Eliot Kimber
integers (although I'm pretty sure the spec allows fractional
percentages).
Post by Eliot Kimber
Thanks,
Eliot
--
Eliot Kimber
http://contrext.com
On 8/15/18, 3:40 PM, "Eliot Kimber" <
I need to extend the options for setting table
widths.
Post by Eliot Kimber
Per the spec, a table's width can be an absolute
measurement, a percentage value, or the keyword "auto".
Right now XWPFTable.setWidth() only takes an integer.
I'd like to extend it to take in addition a
percentage
Post by Eliot Kimber
value or the value "auto" (which I suppose conceptually is an
enumeration
Post by Eliot Kimber
with one possible value).
There doesn't seem to be a class that represents a
percentage value (at least I couldn't find any declarations with the
string
Post by Eliot Kimber
"perc" in them.
Am I missing something for working with percentage
values
Post by Eliot Kimber
in the XWPF API?
Thanks,
E.
--
Eliot Kimber
http://contrext.com
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
Post by Eliot Kimber
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, e-mail: user-***@poi.apache.org
For additional commands, e-mail: user-***@poi.apache.org

Continue reading on narkive:
Loading...