1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <xihelper.hxx>
22 #include <svl/itemset.hxx>
23 #include <svl/sharedstringpool.hxx>
24 #include <editeng/editobj.hxx>
25 #include <tools/urlobj.hxx>
26 #include <editeng/eeitem.hxx>
27 #include <editeng/flditem.hxx>
28 #include <document.hxx>
29 #include <rangelst.hxx>
30 #include <editutil.hxx>
32 #include <xltracer.hxx>
33 #include <xistream.hxx>
34 #include <xistring.hxx>
35 #include <xistyle.hxx>
36 #include <excform.hxx>
37 #include <scmatrix.hxx>
38 #include <documentimport.hxx>
39 #include <sal/log.hxx>
41 // Excel->Calc cell address/range conversion ==================================
45 /** Fills the passed Calc address with the passed Excel cell coordinates without checking any limits. */
46 void lclFillAddress( ScAddress
& rScPos
, sal_uInt16 nXclCol
, sal_uInt32 nXclRow
, SCTAB nScTab
)
48 rScPos
.SetCol( static_cast< SCCOL
>( nXclCol
) );
49 rScPos
.SetRow( static_cast< SCROW
>( nXclRow
) );
50 rScPos
.SetTab( nScTab
);
55 XclImpAddressConverter::XclImpAddressConverter( const XclImpRoot
& rRoot
) :
56 XclAddressConverterBase( rRoot
.GetTracer(), rRoot
.GetScMaxPos() )
60 // cell address ---------------------------------------------------------------
62 bool XclImpAddressConverter::CheckAddress( const XclAddress
& rXclPos
, bool bWarn
)
64 bool bValidCol
= rXclPos
.mnCol
<= mnMaxCol
;
65 bool bValidRow
= rXclPos
.mnRow
<= mnMaxRow
;
66 bool bValid
= bValidCol
&& bValidRow
;
67 if( !bValid
&& bWarn
)
69 mbColTrunc
|= !bValidCol
;
70 mbRowTrunc
|= !bValidRow
;
71 mrTracer
.TraceInvalidAddress( ScAddress(
72 static_cast< SCCOL
>( rXclPos
.mnCol
), static_cast< SCROW
>( rXclPos
.mnRow
), 0 ), maMaxPos
);
77 bool XclImpAddressConverter::ConvertAddress( ScAddress
& rScPos
,
78 const XclAddress
& rXclPos
, SCTAB nScTab
, bool bWarn
)
80 bool bValid
= CheckAddress( rXclPos
, bWarn
);
82 lclFillAddress( rScPos
, rXclPos
.mnCol
, rXclPos
.mnRow
, nScTab
);
86 ScAddress
XclImpAddressConverter::CreateValidAddress(
87 const XclAddress
& rXclPos
, SCTAB nScTab
, bool bWarn
)
89 ScAddress
aScPos( ScAddress::UNINITIALIZED
);
90 if( !ConvertAddress( aScPos
, rXclPos
, nScTab
, bWarn
) )
92 aScPos
.SetCol( static_cast< SCCOL
>( ::std::min( rXclPos
.mnCol
, mnMaxCol
) ) );
93 aScPos
.SetRow( static_cast< SCROW
>( ::std::min( rXclPos
.mnRow
, mnMaxRow
) ) );
94 aScPos
.SetTab( limit_cast
< SCTAB
>( nScTab
, 0, maMaxPos
.Tab() ) );
99 // cell range -----------------------------------------------------------------
101 void XclImpAddressConverter::FillRange(const XclRange
& rXclRange
, ScRange
& rScRange
)
103 const XclAddress aXclStartAdr
= rXclRange
.maFirst
;
104 lclFillAddress(rScRange
.aStart
, aXclStartAdr
.mnCol
, aXclStartAdr
.mnRow
, rScRange
.aStart
.Tab());
105 const XclAddress aXclEndAdr
= rXclRange
.maLast
;
106 lclFillAddress(rScRange
.aEnd
, aXclEndAdr
.mnCol
, aXclEndAdr
.mnRow
, rScRange
.aEnd
.Tab());
109 bool XclImpAddressConverter::ConvertRange( ScRange
& rScRange
,
110 const XclRange
& rXclRange
, SCTAB nScTab1
, SCTAB nScTab2
, bool bWarn
)
112 // check start position
113 bool bValidStart
= CheckAddress( rXclRange
.maFirst
, bWarn
);
116 lclFillAddress( rScRange
.aStart
, rXclRange
.maFirst
.mnCol
, rXclRange
.maFirst
.mnRow
, nScTab1
);
118 // check & correct end position
119 sal_uInt16 nXclCol2
= rXclRange
.maLast
.mnCol
;
120 sal_uInt32 nXclRow2
= rXclRange
.maLast
.mnRow
;
121 if( !CheckAddress( rXclRange
.maLast
, bWarn
) )
123 nXclCol2
= ::std::min( nXclCol2
, mnMaxCol
);
124 nXclRow2
= ::std::min( nXclRow2
, mnMaxRow
);
126 lclFillAddress( rScRange
.aEnd
, nXclCol2
, nXclRow2
, nScTab2
);
131 // cell range list ------------------------------------------------------------
133 void XclImpAddressConverter::ConvertRangeList( ScRangeList
& rScRanges
,
134 const XclRangeList
& rXclRanges
, SCTAB nScTab
, bool bWarn
)
136 rScRanges
.RemoveAll();
137 for( const auto& rXclRange
: rXclRanges
)
139 ScRange
aScRange( ScAddress::UNINITIALIZED
);
140 if( ConvertRange( aScRange
, rXclRange
, nScTab
, nScTab
, bWarn
) )
141 rScRanges
.push_back( aScRange
);
145 // String->EditEngine conversion ==============================================
149 std::unique_ptr
<EditTextObject
> lclCreateTextObject( const XclImpRoot
& rRoot
,
150 const XclImpString
& rString
, XclFontItemType eType
, sal_uInt16 nXFIndex
)
152 std::unique_ptr
<EditTextObject
> pTextObj
;
154 const XclImpXFBuffer
& rXFBuffer
= rRoot
.GetXFBuffer();
155 const XclImpFont
* pFirstFont
= rXFBuffer
.GetFont( nXFIndex
);
156 bool bFirstEscaped
= pFirstFont
&& pFirstFont
->HasEscapement();
158 if( rString
.IsRich() || bFirstEscaped
)
160 const XclImpFontBuffer
& rFontBuffer
= rRoot
.GetFontBuffer();
161 const XclFormatRunVec
& rFormats
= rString
.GetFormats();
163 ScEditEngineDefaulter
& rEE
= rRoot
.GetEditEngine();
164 rEE
.SetTextCurrentDefaults( rString
.GetText() );
166 SfxItemSet
aItemSet( rEE
.GetEmptyItemSet() );
168 rFontBuffer
.FillToItemSet( aItemSet
, eType
, rXFBuffer
.GetFontIndex( nXFIndex
) );
169 ESelection aSelection
;
171 XclFormatRun aNextRun
;
172 XclFormatRunVec::const_iterator aIt
= rFormats
.begin();
173 XclFormatRunVec::const_iterator aEnd
= rFormats
.end();
178 aNextRun
.mnChar
= 0xFFFF;
180 sal_Int32 nLen
= rString
.GetText().getLength();
181 for( sal_Int32 nChar
= 0; nChar
< nLen
; ++nChar
)
183 // reached new different formatted text portion
184 if( nChar
>= aNextRun
.mnChar
)
186 // send items to edit engine
187 rEE
.QuickSetAttribs( aItemSet
, aSelection
);
189 // start new item set
190 aItemSet
.ClearItem();
191 rFontBuffer
.FillToItemSet( aItemSet
, eType
, aNextRun
.mnFontIdx
);
193 // read new formatting information
197 aNextRun
.mnChar
= 0xFFFF;
199 // reset selection start to current position
200 aSelection
.CollapseToEnd();
203 // set end of selection to current position
204 if( rString
.GetText()[ nChar
] == '\n' )
206 ++aSelection
.end
.nPara
;
207 aSelection
.end
.nIndex
= 0;
210 ++aSelection
.end
.nIndex
;
213 // send items of last text portion to edit engine
214 rEE
.QuickSetAttribs( aItemSet
, aSelection
);
216 pTextObj
= rEE
.CreateTextObject();
224 std::unique_ptr
<EditTextObject
> XclImpStringHelper::CreateTextObject(
225 const XclImpRoot
& rRoot
, const XclImpString
& rString
)
227 return lclCreateTextObject( rRoot
, rString
, XclFontItemType::Editeng
, 0 );
230 void XclImpStringHelper::SetToDocument(
231 ScDocumentImport
& rDoc
, const ScAddress
& rPos
, const XclImpRoot
& rRoot
,
232 const XclImpString
& rString
, sal_uInt16 nXFIndex
)
234 if (rString
.GetText().isEmpty())
237 ::std::unique_ptr
< EditTextObject
> pTextObj( lclCreateTextObject( rRoot
, rString
, XclFontItemType::Editeng
, nXFIndex
) );
241 rDoc
.setEditCell(rPos
, std::move(pTextObj
));
245 const OUString
& aStr
= rString
.GetText();
246 if (aStr
.indexOf('\n') != -1 || aStr
.indexOf('\r') != -1)
248 const XclImpXFBuffer
& rXFBuffer
= rRoot
.GetXFBuffer();
249 const XclImpXF
* pXF
= rXFBuffer
.GetXF( nXFIndex
);
250 bool bSingleLine
= pXF
? !pXF
->GetLineBreak() : false;
252 // Multiline content.
253 ScFieldEditEngine
& rEngine
= rDoc
.getDoc().GetEditEngine();
254 rEngine
.SetSingleLine(bSingleLine
);
255 rEngine
.SetTextCurrentDefaults(aStr
);
256 rDoc
.setEditCell(rPos
, rEngine
.CreateTextObject());
257 rEngine
.SetSingleLine(false);
262 rDoc
.setStringCell(rPos
, aStr
);
267 // Header/footer conversion ===================================================
269 XclImpHFConverter::XclImpHFPortionInfo::XclImpHFPortionInfo() :
275 XclImpHFConverter::XclImpHFConverter( const XclImpRoot
& rRoot
) :
277 mrEE( rRoot
.GetHFEditEngine() ),
278 mxFontData( new XclFontData
),
279 meCurrObj( EXC_HF_CENTER
)
283 XclImpHFConverter::~XclImpHFConverter()
287 void XclImpHFConverter::ParseString( const OUString
& rHFString
)
289 // edit engine objects
290 mrEE
.SetText( OUString() );
292 maInfos
.resize( EXC_HF_PORTION_COUNT
);
293 meCurrObj
= EXC_HF_CENTER
;
295 // parser temporaries
296 maCurrText
.truncate();
297 OUStringBuffer aReadFont
; // current font name
298 OUStringBuffer aReadStyle
; // current font style
299 sal_uInt16 nReadHeight
= 0; // current font height
302 /** State of the parser. */
303 enum XclHFParserState
305 xlPSText
, /// Read text, search for functions.
306 xlPSFunc
, /// Read function (token following a '&').
307 xlPSFont
, /// Read font name ('&' is followed by '"', reads until next '"' or ',').
308 xlPSFontStyle
, /// Read font style name (font part after ',', reads until next '"').
309 xlPSHeight
/// Read font height ('&' is followed by num. digits, reads until non-digit).
312 const sal_Unicode
* pChar
= rHFString
.getStr();
313 const sal_Unicode
* pNull
= pChar
+ rHFString
.getLength(); // pointer to terminating null char
319 // --- read text character ---
325 case '&': // new command
329 case '\n': // line break
334 maCurrText
.append(OUStringChar(*pChar
));
339 // --- read control sequence ---
346 case '&': maCurrText
.append("&"); break; // the '&' character
348 case 'L': SetNewPortion( EXC_HF_LEFT
); break; // Left portion
349 case 'C': SetNewPortion( EXC_HF_CENTER
); break; // Center portion
350 case 'R': SetNewPortion( EXC_HF_RIGHT
); break; // Right portion
352 case 'P': InsertField( SvxFieldItem( SvxPageField(), EE_FEATURE_FIELD
) ); break; // page
353 case 'N': InsertField( SvxFieldItem( SvxPagesField(), EE_FEATURE_FIELD
) ); break; // page count
354 case 'D': InsertField( SvxFieldItem( SvxDateField(), EE_FEATURE_FIELD
) ); break; // date
355 case 'T': InsertField( SvxFieldItem( SvxTimeField(), EE_FEATURE_FIELD
) ); break; // time
356 case 'A': InsertField( SvxFieldItem( SvxTableField(), EE_FEATURE_FIELD
) ); break; // table name
358 case 'Z': // file path
359 InsertField( SvxFieldItem( SvxExtFileField(), EE_FEATURE_FIELD
) ); // convert to full name
360 if( (pNull
- pChar
>= 2) && (*(pChar
+ 1) == '&') && (*(pChar
+ 2) == 'F') )
362 // &Z&F found - ignore the &F part
366 case 'F': // file name
367 InsertField( SvxFieldItem( SvxExtFileField( OUString(), SvxFileType::Var
, SvxFileFormat::NameAndExt
), EE_FEATURE_FIELD
) );
370 case 'U': // underline
372 mxFontData
->mnUnderline
= (mxFontData
->mnUnderline
== EXC_FONTUNDERL_SINGLE
) ?
373 EXC_FONTUNDERL_NONE
: EXC_FONTUNDERL_SINGLE
;
375 case 'E': // double underline
377 mxFontData
->mnUnderline
= (mxFontData
->mnUnderline
== EXC_FONTUNDERL_DOUBLE
) ?
378 EXC_FONTUNDERL_NONE
: EXC_FONTUNDERL_DOUBLE
;
380 case 'S': // strikeout
382 mxFontData
->mbStrikeout
= !mxFontData
->mbStrikeout
;
384 case 'X': // superscript
386 mxFontData
->mnEscapem
= (mxFontData
->mnEscapem
== EXC_FONTESC_SUPER
) ?
387 EXC_FONTESC_NONE
: EXC_FONTESC_SUPER
;
389 case 'Y': // subscript
391 mxFontData
->mnEscapem
= (mxFontData
->mnEscapem
== EXC_FONTESC_SUB
) ?
392 EXC_FONTESC_NONE
: EXC_FONTESC_SUB
;
395 case '\"': // font name
396 aReadFont
.setLength(0);
397 aReadStyle
.setLength(0);
401 if( ('0' <= *pChar
) && (*pChar
<= '9') ) // font size
403 nReadHeight
= *pChar
- '0';
410 // --- read font name ---
420 eState
= xlPSFontStyle
;
423 aReadFont
.append(*pChar
);
428 // --- read font style ---
436 if( !aReadFont
.isEmpty() )
437 mxFontData
->maName
= aReadFont
.toString();
438 mxFontData
->maStyle
= aReadStyle
.toString();
442 aReadStyle
.append(*pChar
);
447 // --- read font height ---
451 if( ('0' <= *pChar
) && (*pChar
<= '9') )
453 if( nReadHeight
!= 0xFFFF )
456 nReadHeight
+= (*pChar
- '0');
457 if( nReadHeight
> 1600 ) // max 1600pt = 32000twips
458 nReadHeight
= 0xFFFF;
463 if( (nReadHeight
!= 0) && (nReadHeight
!= 0xFFFF) )
466 mxFontData
->mnHeight
= nReadHeight
* 20;
479 maInfos
[ EXC_HF_LEFT
].mnHeight
+= GetMaxLineHeight( EXC_HF_LEFT
);
480 maInfos
[ EXC_HF_CENTER
].mnHeight
+= GetMaxLineHeight( EXC_HF_CENTER
);
481 maInfos
[ EXC_HF_RIGHT
].mnHeight
+= GetMaxLineHeight( EXC_HF_RIGHT
);
484 void XclImpHFConverter::FillToItemSet( SfxItemSet
& rItemSet
, sal_uInt16 nWhichId
) const
486 ScPageHFItem
aHFItem( nWhichId
);
487 if( maInfos
[ EXC_HF_LEFT
].mxObj
)
488 aHFItem
.SetLeftArea( *maInfos
[ EXC_HF_LEFT
].mxObj
);
489 if( maInfos
[ EXC_HF_CENTER
].mxObj
)
490 aHFItem
.SetCenterArea( *maInfos
[ EXC_HF_CENTER
].mxObj
);
491 if( maInfos
[ EXC_HF_RIGHT
].mxObj
)
492 aHFItem
.SetRightArea( *maInfos
[ EXC_HF_RIGHT
].mxObj
);
493 rItemSet
.Put( aHFItem
);
496 sal_Int32
XclImpHFConverter::GetTotalHeight() const
498 return ::std::max( maInfos
[ EXC_HF_LEFT
].mnHeight
,
499 ::std::max( maInfos
[ EXC_HF_CENTER
].mnHeight
, maInfos
[ EXC_HF_RIGHT
].mnHeight
) );
502 // private --------------------------------------------------------------------
504 sal_uInt16
XclImpHFConverter::GetMaxLineHeight( XclImpHFPortion ePortion
) const
506 sal_uInt16 nMaxHt
= maInfos
[ ePortion
].mnMaxLineHt
;
507 return (nMaxHt
== 0) ? mxFontData
->mnHeight
: nMaxHt
;
510 void XclImpHFConverter::UpdateMaxLineHeight( XclImpHFPortion ePortion
)
512 sal_uInt16
& rnMaxHt
= maInfos
[ ePortion
].mnMaxLineHt
;
513 rnMaxHt
= ::std::max( rnMaxHt
, mxFontData
->mnHeight
);
516 void XclImpHFConverter::UpdateCurrMaxLineHeight()
518 UpdateMaxLineHeight( meCurrObj
);
521 void XclImpHFConverter::SetAttribs()
523 ESelection
& rSel
= GetCurrSel();
526 SfxItemSet
aItemSet( mrEE
.GetEmptyItemSet() );
527 XclImpFont
aFont( GetRoot(), *mxFontData
);
528 aFont
.FillToItemSet( aItemSet
, XclFontItemType::HeaderFooter
);
529 mrEE
.QuickSetAttribs( aItemSet
, rSel
);
530 rSel
.CollapseToEnd();
534 void XclImpHFConverter::ResetFontData()
536 if( const XclImpFont
* pFirstFont
= GetFontBuffer().GetFont( EXC_FONT_APP
) )
537 *mxFontData
= pFirstFont
->GetFontData();
541 mxFontData
->mnHeight
= 200;
545 void XclImpHFConverter::InsertText()
547 if( !maCurrText
.isEmpty() )
549 ESelection
& rSel
= GetCurrSel();
550 OUString
sString(maCurrText
.makeStringAndClear());
551 mrEE
.QuickInsertText(sString
, ESelection(rSel
.end
));
552 rSel
.end
.nIndex
+= sString
.getLength();
553 UpdateCurrMaxLineHeight();
557 void XclImpHFConverter::InsertField( const SvxFieldItem
& rFieldItem
)
559 ESelection
& rSel
= GetCurrSel();
560 mrEE
.QuickInsertField(rFieldItem
, ESelection(rSel
.end
));
562 UpdateCurrMaxLineHeight();
565 void XclImpHFConverter::InsertLineBreak()
567 ESelection
& rSel
= GetCurrSel();
568 mrEE
.QuickInsertText(OUString('\n'), ESelection(rSel
.end
));
571 GetCurrInfo().mnHeight
+= GetMaxLineHeight( meCurrObj
);
572 GetCurrInfo().mnMaxLineHt
= 0;
575 void XclImpHFConverter::CreateCurrObject()
579 GetCurrObj() = mrEE
.CreateTextObject();
582 void XclImpHFConverter::SetNewPortion( XclImpHFPortion eNew
)
584 if( eNew
!= meCurrObj
)
589 mrEE
.SetText( *GetCurrObj() );
591 mrEE
.SetText( OUString() );
596 // URL conversion =============================================================
600 void lclAppendUrlChar( OUString
& rUrl
, sal_Unicode cChar
)
602 // encode special characters
605 case '#': rUrl
+= "%23"; break;
606 case '%': rUrl
+= "%25"; break;
607 default: rUrl
+= OUStringChar( cChar
);
613 void XclImpUrlHelper::DecodeUrl(
614 OUString
& rUrl
, OUString
& rTabName
, bool& rbSameWb
,
615 const XclImpRoot
& rRoot
, const OUString
& rEncodedUrl
)
619 xlUrlInit
, /// Initial state, read string mode character.
620 xlUrlPath
, /// Read URL path.
621 xlUrlFileName
, /// Read file name.
622 xlUrlSheetName
, /// Read sheet name.
623 xlUrlRaw
/// Raw mode. No control characters will occur.
624 } eState
= xlUrlInit
;
626 bool bEncoded
= true;
629 sal_Unicode cCurrDrive
= 0;
630 OUString
aDosBase( INetURLObject( rRoot
.GetBasePath() ).getFSysPath( FSysStyle::Dos
) );
631 if (!aDosBase
.isEmpty() && aDosBase
.match(":\\", 1))
632 cCurrDrive
= aDosBase
[0];
634 const sal_Unicode
* pChar
= rEncodedUrl
.getStr();
640 // --- first character ---
646 case EXC_URLSTART_ENCODED
:
649 case EXC_URLSTART_SELF
:
650 case EXC_URLSTART_SELFENCODED
:
652 eState
= xlUrlSheetName
;
656 eState
= xlUrlFileName
;
660 lclAppendUrlChar( rUrl
, *pChar
);
672 case EXC_URL_DOSDRIVE
:
681 lclAppendUrlChar( rUrl
, *pChar
);
686 rUrl
+= "<NULL-DRIVE!>";
689 case EXC_URL_DRIVEROOT
:
692 lclAppendUrlChar( rUrl
, cCurrDrive
);
699 else // control character in raw name -> DDE link
701 rUrl
+= OUStringChar(EXC_DDE_DELIM
);
705 case EXC_URL_PARENTDIR
:
712 sal_Int32 nLen
= *++pChar
;
713 for( sal_Int32 nChar
= 0; (nChar
< nLen
) && *(pChar
+ 1); ++nChar
)
714 lclAppendUrlChar( rUrl
, *++pChar
);
715 // rUrl.Append( ':' );
720 eState
= xlUrlFileName
;
723 lclAppendUrlChar( rUrl
, *pChar
);
734 case ']': eState
= xlUrlSheetName
; break;
735 default: lclAppendUrlChar( rUrl
, *pChar
);
740 // --- sheet name ---
743 rTabName
+= OUStringChar( *pChar
);
746 // --- raw read mode ---
749 lclAppendUrlChar( rUrl
, *pChar
);
757 void XclImpUrlHelper::DecodeUrl(
758 OUString
& rUrl
, bool& rbSameWb
, const XclImpRoot
& rRoot
, const OUString
& rEncodedUrl
)
762 DecodeUrl( aUrl
, aTabName
, rbSameWb
, rRoot
, rEncodedUrl
);
764 OSL_ENSURE( aTabName
.isEmpty(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" );
767 bool XclImpUrlHelper::DecodeLink( OUString
& rApplic
, OUString
& rTopic
, std::u16string_view aEncUrl
)
769 size_t nPos
= aEncUrl
.find( EXC_DDE_DELIM
);
770 if( nPos
!= std::u16string_view::npos
&& (nPos
> 0) && (nPos
+ 1 < aEncUrl
.size()) )
772 rApplic
= aEncUrl
.substr( 0, nPos
);
773 rTopic
= aEncUrl
.substr( nPos
+ 1 );
779 // Cached Values ==============================================================
781 XclImpCachedValue::XclImpCachedValue( XclImpStream
& rStrm
) :
785 mnType
= rStrm
.ReaduInt8();
788 case EXC_CACHEDVAL_EMPTY
:
791 case EXC_CACHEDVAL_DOUBLE
:
792 mfValue
= rStrm
.ReadDouble();
794 case EXC_CACHEDVAL_STRING
:
795 maStr
= rStrm
.ReadUniString();
797 case EXC_CACHEDVAL_BOOL
:
798 case EXC_CACHEDVAL_ERROR
:
801 mnBoolErr
= rStrm
.ReaduInt8();
804 std::unique_ptr
<ScTokenArray
> pScTokArr
= rStrm
.GetRoot().GetOldFmlaConverter().GetBoolErr(
805 XclTools::ErrorToEnum( fVal
, mnType
== EXC_CACHEDVAL_ERROR
, mnBoolErr
) );
807 mxTokArr
= std::move( pScTokArr
);
811 OSL_FAIL( "XclImpCachedValue::XclImpCachedValue - unknown data type" );
815 XclImpCachedValue::~XclImpCachedValue()
819 FormulaError
XclImpCachedValue::GetScError() const
821 return (mnType
== EXC_CACHEDVAL_ERROR
) ? XclTools::GetScErrorCode( mnBoolErr
) : FormulaError::NONE
;
824 // Matrix Cached Values ==============================================================
826 XclImpCachedMatrix::XclImpCachedMatrix( XclImpStream
& rStrm
) :
830 mnScCols
= rStrm
.ReaduInt8();
831 mnScRows
= rStrm
.ReaduInt16();
833 if( rStrm
.GetRoot().GetBiff() <= EXC_BIFF5
)
835 // in BIFF2-BIFF7: 256 columns represented by 0 columns
841 // in BIFF8: columns and rows decreased by 1
846 //assuming worst case scenario of unknown types
847 const size_t nMinRecordSize
= 1;
848 const size_t nMaxRows
= rStrm
.GetRecLeft() / (nMinRecordSize
* mnScCols
);
849 if (mnScRows
> nMaxRows
)
851 SAL_WARN("sc", "Parsing error: " << nMaxRows
<<
852 " max possible rows, but " << mnScRows
<< " claimed, truncating");
856 for( SCSIZE nScRow
= 0; nScRow
< mnScRows
; ++nScRow
)
857 for( SCSIZE nScCol
= 0; nScCol
< mnScCols
; ++nScCol
)
858 maValueList
.push_back( std::make_unique
<XclImpCachedValue
>( rStrm
) );
861 XclImpCachedMatrix::~XclImpCachedMatrix()
865 ScMatrixRef
XclImpCachedMatrix::CreateScMatrix( svl::SharedStringPool
& rPool
) const
867 ScMatrixRef xScMatrix
;
868 OSL_ENSURE( mnScCols
* mnScRows
== maValueList
.size(), "XclImpCachedMatrix::CreateScMatrix - element count mismatch" );
869 if( mnScCols
&& mnScRows
&& static_cast< sal_uLong
>( mnScCols
* mnScRows
) <= maValueList
.size() )
871 xScMatrix
= new ScMatrix(mnScCols
, mnScRows
, 0.0);
872 XclImpValueList::const_iterator itValue
= maValueList
.begin();
873 for( SCSIZE nScRow
= 0; nScRow
< mnScRows
; ++nScRow
)
875 for( SCSIZE nScCol
= 0; nScCol
< mnScCols
; ++nScCol
)
877 switch( (*itValue
)->GetType() )
879 case EXC_CACHEDVAL_EMPTY
:
880 // Excel shows 0.0 here, not an empty cell
881 xScMatrix
->PutEmpty( nScCol
, nScRow
);
883 case EXC_CACHEDVAL_DOUBLE
:
884 xScMatrix
->PutDouble( (*itValue
)->GetValue(), nScCol
, nScRow
);
886 case EXC_CACHEDVAL_STRING
:
887 xScMatrix
->PutString(rPool
.intern((*itValue
)->GetString()), nScCol
, nScRow
);
889 case EXC_CACHEDVAL_BOOL
:
890 xScMatrix
->PutBoolean( (*itValue
)->GetBool(), nScCol
, nScRow
);
892 case EXC_CACHEDVAL_ERROR
:
893 xScMatrix
->PutError( (*itValue
)->GetScError(), nScCol
, nScRow
);
896 OSL_FAIL( "XclImpCachedMatrix::CreateScMatrix - unknown value type" );
897 xScMatrix
->PutEmpty( nScCol
, nScRow
);
906 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */