summaryrefslogtreecommitdiff
path: root/sc/source/ui/docshell
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/docshell')
-rw-r--r--sc/source/ui/docshell/impex.cxx112
1 files changed, 100 insertions, 12 deletions
diff --git a/sc/source/ui/docshell/impex.cxx b/sc/source/ui/docshell/impex.cxx
index 7b9559169bb2..714066c9fafd 100644
--- a/sc/source/ui/docshell/impex.cxx
+++ b/sc/source/ui/docshell/impex.cxx
@@ -62,6 +62,7 @@
#include <vcl/weld.hxx>
#include <editeng/editobj.hxx>
#include <svl/numformat.hxx>
+#include <rtl/character.hxx>
#include <memory>
#include <string_view>
@@ -1096,26 +1097,24 @@ static bool lcl_PutString(
sal_Int32 nStart[nMaxNumberParts];
sal_Int32 nEnd[nMaxNumberParts];
+ bool bIso;
sal_uInt16 nDP, nMP, nYP;
switch ( nColFormat )
{
- case SC_COL_YMD: nDP = 2; nMP = 1; nYP = 0; break;
- case SC_COL_MDY: nDP = 1; nMP = 0; nYP = 2; break;
+ case SC_COL_YMD: nDP = 2; nMP = 1; nYP = 0; bIso = true; break;
+ case SC_COL_MDY: nDP = 1; nMP = 0; nYP = 2; bIso = false; break;
case SC_COL_DMY:
- default: nDP = 0; nMP = 1; nYP = 2; break;
+ default: nDP = 0; nMP = 1; nYP = 2; bIso = false; break;
}
sal_uInt16 nFound = 0;
bool bInNum = false;
- for ( sal_Int32 nPos=0; nPos<nLen && (bInNum ||
- nFound<nMaxNumberParts); nPos++ )
+ for (sal_Int32 nPos = 0; nPos < nLen && (bInNum || nFound < nMaxNumberParts); ++nPos)
{
- if (bInNum && nFound == 3 && nColFormat == SC_COL_YMD &&
- nPos <= nStart[nFound]+2 && rStr[nPos] == 'T')
- bInNum = false; // ISO-8601: YYYY-MM-DDThh:mm...
- else if ((((!bInNum && nFound==nMP) || (bInNum && nFound==nMP+1))
- && ScGlobal::getCharClass().isLetterNumeric( rStr, nPos))
- || ScGlobal::getCharClass().isDigit( rStr, nPos))
+ bool bLetter = false;
+ if (rtl::isAsciiDigit(rStr[nPos]) ||
+ (((!bInNum && nFound==nMP) || (bInNum && nFound==nMP+1))
+ && (bLetter = ScGlobal::getCharClass().isLetterNumeric( rStr, nPos))))
{
if (!bInNum)
{
@@ -1124,9 +1123,98 @@ static bool lcl_PutString(
++nFound;
}
nEnd[nFound-1] = nPos;
+ if (bIso && (bLetter || (2 <= nFound && nFound <= 6 && nPos > nStart[nFound-1] + 1)))
+ // Each M,D,h,m,s at most 2 digits.
+ bIso = false;
}
else
+ {
bInNum = false;
+ if (bIso)
+ {
+ // ([+-])YYYY-MM-DD([T ]hh:mm(:ss(.fff)))(([+-])TZ)
+ // XXX NOTE: timezone is accepted here, but number
+ // formatter parser will not, so the end result will be
+ // type Text to preserve timezone information.
+ switch (rStr[nPos])
+ {
+ case '+':
+ if (nFound >= 5 && nPos == nEnd[nFound-1] + 1)
+ // Accept timezone offset.
+ ;
+ else if (nPos > 0)
+ // Accept one leading sign.
+ bIso = false;
+ break;
+ case '-':
+ if (nFound >= 5 && nPos == nEnd[nFound-1] + 1)
+ // Accept timezone offset.
+ ;
+ else if (nFound == 0 && nPos > 0)
+ // Accept one leading sign.
+ bIso = false;
+ else if (nFound < 1 || 2 < nFound || nPos != nEnd[nFound-1] + 1)
+ // Not immediately after 1 or 1-2
+ bIso = false;
+ break;
+ case 'T':
+ case ' ':
+ if (nFound != 3 || nPos != nEnd[nFound-1] + 1)
+ // Not immediately after 1-2-3
+ bIso = false;
+ break;
+ case ':':
+ if (nFound < 4 || 5 < nFound || nPos != nEnd[nFound-1] + 1)
+ // Not at 1-2-3T4:5:
+ bIso = false;
+ break;
+ case '.':
+ case ',':
+ if (nFound != 6 || nPos != nEnd[nFound-1] + 1)
+ // Not at 1-2-3T4:5:6.
+ bIso = false;
+ break;
+ case 'Z':
+ if (nFound >= 5 && nPos == nEnd[nFound-1] + 1)
+ // Accept Zero timezone.
+ ;
+ else
+ bIso = false;
+ break;
+ default:
+ bIso = false;
+ }
+ }
+ }
+ }
+
+ if (nFound < 3)
+ bIso = false;
+
+ if (bIso)
+ {
+ // Leave conversion and detection of various possible number
+ // formats to the number formatter. ISO is recognized in any locale
+ // so we can directly use the document's formatter.
+ sal_uInt32 nFormat = 0;
+ double fVal = 0.0;
+ SvNumberFormatter* pDocFormatter = rDoc.GetFormatTable();
+ if (pDocFormatter->IsNumberFormat( rStr, nFormat, fVal))
+ {
+ if (pDocFormatter->GetType(nFormat) & SvNumFormatType::DATE)
+ {
+ ScAddress aPos(nCol,nRow,nTab);
+ if (bUseDocImport)
+ rDocImport.setNumericCell(aPos, fVal);
+ else
+ rDoc.SetValue(aPos, fVal);
+ rDoc.SetNumberFormat(aPos, nFormat);
+
+ return bMultiLine; // success
+ }
+ }
+ // If we reach here it is type Text (e.g. timezone or trailing
+ // characters). Handled below.
}
if ( nFound == 1 )
@@ -1163,7 +1251,7 @@ static bool lcl_PutString(
}
}
- if ( nFound >= 3 )
+ if (!bIso && nFound >= 3)
{
using namespace ::com::sun::star;
bool bSecondCal = false;