/ / XSL: Wyrównanie pionowe FO liczb dodatnich i ujemnych - xml, pdf, xslt-2.0, xsl-fo

XSL: wyrównanie pionowe FO liczb dodatnich i ujemnych - xml, pdf, xslt-2.0, xsl-fo

Próbuję sformatować to wejście XML:

<item name="foo" amt1="100" amt2="200" />
<item name="bar" amt1="-300" amt2="-400" />

w formacie PDF (przy użyciu RenderX) jako:

foo |  100  |  200
--- | ----- | -----
bar | (300) | (400)

ale następujące:

<xsl:for-each select="item">
...
<fo:table-row>
<fo:table-cell>
<fo:block text-align="left">
<xsl:value-of select="@name"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block text-align="right">
<xsl:value-of select="format-number(@amt1, "#,###;(#,###)")"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block text-align="right">
<xsl:value-of select="format-number(@amt2, "#,###;(#,###)")"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>

jest wyprowadzane jako:

foo |   100 |   200
--- | ----- | -----
bar | (300) | (400)

gdzie liczby dodatnie w wierszu 1 i ujemneliczby w wierszu 2 są wyrównane do prawej, ale chciałbym również, aby były wyrównane w pionie do ostatniej liczby całkowitej liczby zamiast ostatniego znaku. Jedyne rozwiązanie, jakie przychodzi mi do głowy, to mieć xsl: wybierz ustawienie dodatkowego atrybutu „padding-after” na wszystkich dodatnich liczbach całkowitych, aby przesunąć je na ostatnią liczbę całkowitą z liczb ujemnych. Czy jest lepszy sposób na zrobienie tego?

Rozwiązanie:

<fo:block text-align="right">
<xsl:value-of select="format-number(@amt1, "#,###;(#,###)")"/>
<fo:leader leader-pattern="use-content" leader-length="5pt" leader-pattern-width="5pt">
<xsl:choose>
<xsl:when test="@cy_amt &lt;= "0"">)</xsl:when>
</xsl:choose>
</fo:leader>
</fo:block>

Odpowiedzi:

0 dla odpowiedzi № 1

Lista / rozwiązania liderów nie są idealne z mojegopunktu widzenia, ponieważ wymagają wyrównania liczb do prawej. Dlatego jeśli nie wiesz, jak długie mogą być twoje liczby, musisz zostawić ważną poziomą przestrzeń, nawet jeśli przez większość czasu liczby są małe i mogą znajdować się bliżej jakiejś etykiety.

Używam następującego szablonu, który mi na to pozwalawyrównaj kilka liczb, dodając niewidoczne zera po lewej stronie. Tak więc największa liczba jest wyrównana do lewej, a pozostałe liczby są wyrównane do jej przecinka dziesiętnego.

Oczywiste zastrzeżenia są - musisz wiedzieć, co tonajwiększa liczba to - liczby ujemne nie są obsługiwane (ale można to naprawić, mogę to zrobić, kiedy będę tego potrzebować, upewnię się, że zaktualizuję tę odpowiedź) - musisz użyć czcionki, w której wszystkie cyfry używają tej samej poziomej przestrzeni.

<xsl:template name="tools_formatters_number">
<xsl:param name="integer-positions" select="0" />
<xsl:param name="number" />
<xsl:param name="mask" select=""###,###,###,###,###,##0.00"" />

<xsl:choose>
<xsl:variable name="positions" select="$integer-positions + floor(($integer-positions - 1) div 3)" />

<xsl:variable name="mask-zeroed" select="translate($mask, "#", "0")" />
<xsl:variable name="mask-zeroed-left" select="substring-before($mask-zeroed, ".")" />
<xsl:variable name="mask-zeroed-right" select="concat(".", substring-after($mask-zeroed, "."))" />

<xsl:variable name="sub-mask-zeroed-left" select="substring($mask-zeroed-left, string-length($mask-zeroed-left) - $positions + 1, $positions)" />

<xsl:variable name="mask2" select="concat($sub-mask-zeroed-left, $mask-zeroed-right)" />
<xsl:variable name="fnumber" select="format-number($number, $mask2)" />

<xsl:variable name="pnumber" select="string-length(substring-before(format-number($number, $mask), "."))" />
<xsl:variable name="posnumber" select="$pnumber + floor(($pnumber - 1) div 3) + string-length(substring-after($fnumber, ".")) + 1" />

<xsl:variable name="whitepart" select="substring($fnumber, 1, string-length($fnumber) - $posnumber)" />
<xsl:variable name="blackpart" select="substring($fnumber, string-length($fnumber) - $posnumber + 1, $posnumber)" />

<inline color="white"><xsl:value-of select="$whitepart" /></inline>
<xsl:value-of select="$blackpart" />
</xsl:choose>
</xsl:template>

Oto krótki opis tego, co zawiera każdy parametr / zmienna.

Przykładem są wartości w nawiasach klamrowych.

  • integer-position mówi, ile cyfr należy pokazać przed separatorem dziesiętnym. {7}
  • liczba to liczba, która ma zostać wyświetlona. {4242,42}
  • maska ​​to standardowa maska ​​do formatowania liczb.Kod szablonu jest dostosowany do tej maski, możesz dodać tysiące grup po lewej stronie i cokolwiek chcesz po prawej, ale każda grupa musi składać się z dokładnie trzech cyfr po lewej stronie separatora dziesiętnego. {###, ###, ###, ###, ###, ## 0,00}
  • pozycje to liczby całkowite, z uwzględnieniem separatorów tysięcy {9}
  • maska ​​wyzerowana to maska ​​bez opcjonalnych cyfr po lewej stronie {000 000,00}
  • mask-zeroed-left to całkowita część wartości {000 000} z maską wyzerowaną
  • mask-zeroed-right to dziesiętna część wartości mask-zeroed {.00}
  • sub-mask-zeroed-left to mask-zeroed-left ograniczone do cyfr pozycji. {0,000 000}
  • maska2 dodaje prawą część do maski podrzędnej zerowanej-lewej. {0,000,000,00}
  • fnumber jest formatowany liczbowo z maską2. {0,004 242,42}
  • pnumber to liczba cyfr w całkowitej części liczby {4}
  • posnumber to liczba symboli, które mają być pokazane {(5 + 3 =) 8}
  • Biała część to część spacji, która zostanie wydrukowana na biało {0,00}
  • czarna część to rzeczywista liczba {4 242,42}

Przykład użycia:

<xsl:call-template name="tools_formatters_number">
<xsl:with-param name="integer-positions" select="7" />
<xsl:with-param name="number" select=""4242.42"" />
</xsl:call-template>