write trailing text subformat also to Excel .xls and .xlsx, tdf#92457

... without generating  0;;;@  from  0;@  that has different semantics.

Introduce css::util::NumberFormat::EMPTY to properly flag empty
subformats and distinguish from UNDEFINED, everything else would be an
ugly hack.

SvNumberformat::GetMappedFormatstring() now correctly supports the
trailing text subformat, so exports using it should get that
automatically.

Change-Id: If9a1bcc5ec5dfcf46688035e2b1428ab4747a68d
diff --git a/offapi/com/sun/star/util/NumberFormat.idl b/offapi/com/sun/star/util/NumberFormat.idl
index 927bdf8..2bc297a 100644
--- a/offapi/com/sun/star/util/NumberFormat.idl
+++ b/offapi/com/sun/star/util/NumberFormat.idl
@@ -93,6 +93,12 @@ published constants NumberFormat
     */
    const short UNDEFINED = 2048;


    /** @internal is used to flag an empty sub format.
        @since LibreOffice 5.1
     */
    const short EMPTY = 4096;

};


diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx
index c645034..03c2078 100644
--- a/svl/source/numbers/zformat.cxx
+++ b/svl/source/numbers/zformat.cxx
@@ -893,7 +893,8 @@ SvNumberformat::SvNumberformat(OUString& rString,
                }
                if (sStr.isEmpty())
                {
                    // empty sub format
                    // Empty sub format.
                    NumFor[nIndex].Info().eScannedType = css::util::NumberFormat::EMPTY;
                }
                else
                {
@@ -2202,7 +2203,7 @@ bool SvNumberformat::GetOutputString(double fNumber,
        *ppColor = NumFor[nIx].GetColor();
        const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info();
        const sal_uInt16 nAnz = NumFor[nIx].GetCount();
        if (nAnz == 0 && rInfo.eScannedType == css::util::NumberFormat::UNDEFINED)
        if (nAnz == 0 && rInfo.eScannedType == css::util::NumberFormat::EMPTY)
        {
            return false; // Empty => nothing
        }
@@ -4722,7 +4723,7 @@ OUString SvNumberformat::GetMappedFormatstring( const NfKeywordTable& rKeywords,
                    eOp1 == NUMBERFORMAT_OP_GE && fLimit1 == 0.0 &&
                    eOp2 == NUMBERFORMAT_OP_NO && fLimit2 == 0.0 );
    // with 3 or more subformats [>0];[<0];[=0] is implied if no condition specified,
    // note that subformats may be empty (;;;) and NumFor[2].GetnAnz()>0 is not checked.
    // note that subformats may be empty (;;;) and NumFor[2].GetCount()>0 is not checked.
    bDefault[2] = ( !bDefault[0] && !bDefault[1] &&
                    eOp1 == NUMBERFORMAT_OP_GT && fLimit1 == 0.0 &&
                    eOp2 == NUMBERFORMAT_OP_LT && fLimit2 == 0.0 );
@@ -4762,7 +4763,7 @@ OUString SvNumberformat::GetMappedFormatstring( const NfKeywordTable& rKeywords,
    int nSub = 0; // subformats delimited so far
    for ( int n=0; n<4; n++ )
    {
        if ( n > 0 )
        if ( n > 0 && NumFor[n].Info().eScannedType != css::util::NumberFormat::UNDEFINED )
        {
            nSem++;
        }
diff --git a/xmloff/source/style/xmlnumfe.cxx b/xmloff/source/style/xmlnumfe.cxx
index 3ccf074..d0da09b 100644
--- a/xmloff/source/style/xmlnumfe.cxx
+++ b/xmloff/source/style/xmlnumfe.cxx
@@ -1006,9 +1006,6 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt

    // #101606# An empty subformat is a valid number-style resulting in an
    // empty display string for the condition of the subformat.
    if ( nFmtType == css::util::NumberFormat::UNDEFINED && rFormat.GetNumForType( nPart,
                0, false ) == 0 )
        nFmtType = 0;

    XMLTokenEnum eType = XML_TOKEN_INVALID;
    switch ( nFmtType )
@@ -1016,6 +1013,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt
        // type is 0 if a format contains no recognized elements
        // (like text only) - this is handled as a number-style.
        case 0:
        case css::util::NumberFormat::EMPTY:
        case css::util::NumberFormat::NUMBER:
        case css::util::NumberFormat::SCIENTIFIC:
        case css::util::NumberFormat::FRACTION: