1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: impex.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // System - Includes -----------------------------------------------------
42 #define GLOBALOVERFLOW
45 // INCLUDE ---------------------------------------------------------------
50 #include <osl/endian.h>
51 #include <i18npool/mslangid.hxx>
52 #include <tools/list.hxx>
53 #include <tools/string.hxx>
54 #include <rtl/math.hxx>
55 #include <svtools/htmlout.hxx>
56 #include <svtools/zforlist.hxx>
57 #define _SVSTDARR_ULONGS
58 #include <svtools/svstdarr.hxx>
59 #include <sot/formats.hxx>
60 #include <sfx2/mieclip.hxx>
61 #include <unotools/charclass.hxx>
62 #include <unotools/collatorwrapper.hxx>
63 #include <unotools/calendarwrapper.hxx>
64 #include <com/sun/star/i18n/CalendarFieldIndex.hpp>
65 #include <unotools/transliterationwrapper.hxx>
68 #include "scerrors.hxx"
70 #include "undoblk.hxx"
71 #include "rangenam.hxx"
72 #include "viewdata.hxx"
73 #include "tabvwsh.hxx"
75 #include "asciiopt.hxx"
77 #include "docoptio.hxx"
78 #include "progress.hxx"
79 #include "scitems.hxx"
80 #include "editable.hxx"
81 #include "compiler.hxx"
82 #include "warnbox.hxx"
87 #include "editutil.hxx"
88 #include "patattr.hxx"
89 #include "docpool.hxx"
90 #include "stringutil.hxx"
92 #include "globstr.hrc"
93 #include <vcl/msgbox.hxx>
94 #include <vcl/svapp.hxx>
95 #include <osl/module.hxx>
97 //========================================================================
101 const String SYLK_LF
= String::CreateFromAscii("\x1b :");
102 const String DOUBLE_SEMICOLON
= String::CreateFromAscii(";;");
103 const String DOUBLE_DOUBLEQUOTE
= String::CreateFromAscii("\"\"");
108 SYLK_SCALC3
, // Wrote wrongly quoted strings and unescaped semicolons.
109 SYLK_OOO32
, // Correct strings, plus multiline content.
110 SYLK_OWN
, // Place our new versions, if any, before this value.
111 SYLK_OTHER
// Assume that aliens wrote correct strings.
115 // Gesamtdokument ohne Undo
118 ScImportExport::ScImportExport( ScDocument
* p
)
119 : pDocSh( PTR_CAST(ScDocShell
,p
->GetDocumentShell()) ), pDoc( p
),
120 nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
121 bFormulas( FALSE
), bIncludeFiltered( TRUE
),
122 bAll( TRUE
), bSingle( TRUE
), bUndo( FALSE
),
123 bOverflow( FALSE
), mbApi( true ), mExportTextOptions()
129 // Insert am Punkt ohne Bereichschecks
132 ScImportExport::ScImportExport( ScDocument
* p
, const ScAddress
& rPt
)
133 : pDocSh( PTR_CAST(ScDocShell
,p
->GetDocumentShell()) ), pDoc( p
),
135 nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
136 bFormulas( FALSE
), bIncludeFiltered( TRUE
),
137 bAll( FALSE
), bSingle( TRUE
), bUndo( BOOL( pDocSh
!= NULL
) ),
138 bOverflow( FALSE
), mbApi( true ), mExportTextOptions()
145 // ctor with a range is only used for export
146 //! ctor with a string (and bSingle=TRUE) is also used for DdeSetData
148 ScImportExport::ScImportExport( ScDocument
* p
, const ScRange
& r
)
149 : pDocSh( PTR_CAST(ScDocShell
,p
->GetDocumentShell()) ), pDoc( p
),
151 nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
152 bFormulas( FALSE
), bIncludeFiltered( TRUE
),
153 bAll( FALSE
), bSingle( FALSE
), bUndo( BOOL( pDocSh
!= NULL
) ),
154 bOverflow( FALSE
), mbApi( true ), mExportTextOptions()
158 // Zur Zeit nur in einer Tabelle!
159 aRange
.aEnd
.SetTab( aRange
.aStart
.Tab() );
162 // String auswerten: Entweder Bereich, Punkt oder Gesamtdoc (bei Fehler)
163 // Falls eine View existiert, wird die TabNo der View entnommen!
166 ScImportExport::ScImportExport( ScDocument
* p
, const String
& rPos
)
167 : pDocSh( PTR_CAST(ScDocShell
,p
->GetDocumentShell()) ), pDoc( p
),
168 nSizeLimit( 0 ), cSep( '\t' ), cStr( '"' ),
169 bFormulas( FALSE
), bIncludeFiltered( TRUE
),
170 bAll( FALSE
), bSingle( TRUE
), bUndo( BOOL( pDocSh
!= NULL
) ),
171 bOverflow( FALSE
), mbApi( true ), mExportTextOptions()
176 SCTAB nTab
= ScDocShell::GetCurTab();
177 aRange
.aStart
.SetTab( nTab
);
179 // Benannter Bereich?
180 ScRangeName
* pRange
= pDoc
->GetRangeName();
184 if( pRange
->SearchName( aPos
, nPos
) )
186 ScRangeData
* pData
= (*pRange
)[ nPos
];
187 if( pData
->HasType( RT_REFAREA
)
188 || pData
->HasType( RT_ABSAREA
)
189 || pData
->HasType( RT_ABSPOS
) )
190 pData
->GetSymbol( aPos
); // mit dem Inhalt weitertesten
193 formula::FormulaGrammar::AddressConvention eConv
= pDoc
->GetAddressConvention();
195 if( aRange
.Parse( aPos
, pDoc
, eConv
) & SCA_VALID
)
198 else if( aRange
.aStart
.Parse( aPos
, pDoc
, eConv
) & SCA_VALID
)
199 aRange
.aEnd
= aRange
.aStart
;
205 ScImportExport::~ScImportExport()
212 void ScImportExport::SetExtOptions( const ScAsciiOptions
& rOpt
)
217 pExtOptions
= new ScAsciiOptions( rOpt
);
219 // "normale" Optionen uebernehmen
221 cSep
= rOpt
.GetFieldSeps().GetChar(0);
222 cStr
= rOpt
.GetTextSep();
226 BOOL
ScImportExport::IsFormatSupported( ULONG nFormat
)
228 return BOOL( nFormat
== FORMAT_STRING
229 || nFormat
== SOT_FORMATSTR_ID_SYLK
230 || nFormat
== SOT_FORMATSTR_ID_LINK
231 || nFormat
== SOT_FORMATSTR_ID_HTML
232 || nFormat
== SOT_FORMATSTR_ID_HTML_SIMPLE
233 || nFormat
== SOT_FORMATSTR_ID_DIF
);
237 //////////////////////////////////////////////////////////////////////////////
239 // Vorbereitung fuer Undo: Undo-Dokument erzeugen
242 BOOL
ScImportExport::StartPaste()
246 ScEditableTester
aTester( pDoc
, aRange
);
247 if ( !aTester
.IsEditable() )
249 InfoBox
aInfoBox(Application::GetDefDialogParent(),
250 ScGlobal::GetRscString( aTester
.GetMessageId() ) );
255 if( bUndo
&& pDocSh
&& pDoc
->IsUndoEnabled())
257 pUndoDoc
= new ScDocument( SCDOCMODE_UNDO
);
258 pUndoDoc
->InitUndo( pDoc
, aRange
.aStart
.Tab(), aRange
.aEnd
.Tab() );
259 pDoc
->CopyToDocument( aRange
, IDF_ALL
, FALSE
, pUndoDoc
);
264 // Nachbereitung Insert: Undo/Redo-Aktionen erzeugen, Invalidate/Repaint
267 void ScImportExport::EndPaste()
269 BOOL bHeight
= pDocSh
&& pDocSh
->AdjustRowHeight(
270 aRange
.aStart
.Row(), aRange
.aEnd
.Row(), aRange
.aStart
.Tab() );
272 if( pUndoDoc
&& pDoc
->IsUndoEnabled() )
274 ScDocument
* pRedoDoc
= new ScDocument( SCDOCMODE_UNDO
);
275 pRedoDoc
->InitUndo( pDoc
, aRange
.aStart
.Tab(), aRange
.aEnd
.Tab() );
276 pDoc
->CopyToDocument( aRange
, IDF_ALL
, FALSE
, pRedoDoc
);
277 ScMarkData aDestMark
;
278 aDestMark
.SelectOneTable( aRange
.aStart
.Tab() );
279 pDocSh
->GetUndoManager()->AddUndoAction(
280 new ScUndoPaste( pDocSh
,
281 aRange
.aStart
.Col(), aRange
.aStart
.Row(), aRange
.aStart
.Tab(),
282 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), aRange
.aEnd
.Tab(), aDestMark
,
283 pUndoDoc
, pRedoDoc
, IDF_ALL
, NULL
,NULL
,NULL
,NULL
) );
289 pDocSh
->PostPaint( aRange
, PAINT_GRID
); // AdjustRowHeight paintet evtl. selber
290 pDocSh
->SetDocumentModified();
292 ScTabViewShell
* pViewSh
= ScTabViewShell::GetActiveViewShell();
294 pViewSh
->UpdateInputHandler();
298 /////////////////////////////////////////////////////////////////////////////
302 BOOL
ScImportExport::ImportData( SvData
& rData
)
304 ULONG nFmt
= rData
.GetFormat();
305 if ( nFmt
== SOT_FORMATSTR_ID_HTML_SIMPLE
)
307 MSE40HTMLClipFormatObj aMSE40ClpObj
;
308 if ( aMSE40ClpObj
.GetData( rData
) )
310 SvStream
* pStream
= aMSE40ClpObj
.GetStream();
311 return ImportStream( *pStream
, nFmt
);
318 ULONG nSize
= rData
.GetMinMemorySize();
319 rData
.GetData( &pMem
, TRANSFER_REFERENCE
);
320 if( nFmt
== FORMAT_STRING
321 || nFmt
== FORMAT_RTF
322 || nFmt
== SOT_FORMATSTR_ID_SYLK
323 || nFmt
== SOT_FORMATSTR_ID_HTML
324 || nFmt
== SOT_FORMATSTR_ID_DIF
)
326 //! String? Unicode??
328 // Stringende ermitteln!
329 sal_Char
* pBegin
= (sal_Char
*) pMem
;
330 sal_Char
* pEnd
= (sal_Char
*) pMem
+ nSize
;
333 while( pBegin
!= pEnd
&& *pBegin
!= '\0' )
335 // #72909# MT says only STRING has to be zero-terminated
336 DBG_ASSERT( pBegin
!= pEnd
|| nFmt
!= FORMAT_STRING
, "non zero-terminated String" )
338 SvMemoryStream
aStrm( pMem
, nSize
, STREAM_READ
);
339 return ImportStream( aStrm
, nFmt
);
345 BOOL
ScImportExport::ImportData( const String
& /* rMimeType */,
346 const ::com::sun::star::uno::Any
& /* rValue */ )
348 DBG_ASSERT( !this, "Implementation is missing" );
352 BOOL
ScImportExport::ExportData( const String
& rMimeType
,
353 ::com::sun::star::uno::Any
& rValue
)
355 SvMemoryStream aStrm
;
356 // mba: no BaseURL for data exchange
357 if( ExportStream( aStrm
, String(),
358 SotExchange::GetFormatIdFromMimeType( rMimeType
) ))
361 rValue
<<= ::com::sun::star::uno::Sequence
< sal_Int8
>(
362 (sal_Int8
*)aStrm
.GetData(),
363 aStrm
.Seek( STREAM_SEEK_TO_END
) );
370 BOOL
ScImportExport::ImportString( const ::rtl::OUString
& rText
, ULONG nFmt
)
374 // formats supporting unicode
377 ScImportStringStream
aStrm( rText
);
378 return ImportStream( aStrm
, String(), nFmt
);
379 // ImportStream must handle RTL_TEXTENCODING_UNICODE
384 rtl_TextEncoding eEnc
= gsl_getSystemTextEncoding();
385 ::rtl::OString
aTmp( rText
.getStr(), rText
.getLength(), eEnc
);
386 SvMemoryStream
aStrm( (void*)aTmp
.getStr(), aTmp
.getLength() * sizeof(sal_Char
), STREAM_READ
);
387 aStrm
.SetStreamCharSet( eEnc
);
388 SetNoEndianSwap( aStrm
); //! no swapping in memory
389 return ImportStream( aStrm
, String(), nFmt
);
395 BOOL
ScImportExport::ExportString( ::rtl::OUString
& rText
, ULONG nFmt
)
397 DBG_ASSERT( nFmt
== FORMAT_STRING
, "ScImportExport::ExportString: Unicode not supported for other formats than FORMAT_STRING" );
398 if ( nFmt
!= FORMAT_STRING
)
400 rtl_TextEncoding eEnc
= gsl_getSystemTextEncoding();
402 BOOL bOk
= ExportByteString( aTmp
, eEnc
, nFmt
);
403 rText
= UniString( aTmp
, eEnc
);
406 // nSizeLimit not needed for OUString
408 SvMemoryStream aStrm
;
409 aStrm
.SetStreamCharSet( RTL_TEXTENCODING_UNICODE
);
410 SetNoEndianSwap( aStrm
); //! no swapping in memory
411 // mba: no BaseURL for data exc
412 if( ExportStream( aStrm
, String(), nFmt
) )
414 aStrm
<< (sal_Unicode
) 0;
415 aStrm
.Seek( STREAM_SEEK_TO_END
);
417 rText
= rtl::OUString( (const sal_Unicode
*) aStrm
.GetData() );
420 rText
= rtl::OUString();
423 // ExportStream must handle RTL_TEXTENCODING_UNICODE
427 BOOL
ScImportExport::ExportByteString( ByteString
& rText
, rtl_TextEncoding eEnc
, ULONG nFmt
)
429 DBG_ASSERT( eEnc
!= RTL_TEXTENCODING_UNICODE
, "ScImportExport::ExportByteString: Unicode not supported" );
430 if ( eEnc
== RTL_TEXTENCODING_UNICODE
)
431 eEnc
= gsl_getSystemTextEncoding();
434 nSizeLimit
= STRING_MAXLEN
;
436 SvMemoryStream aStrm
;
437 aStrm
.SetStreamCharSet( eEnc
);
438 SetNoEndianSwap( aStrm
); //! no swapping in memory
439 // mba: no BaseURL for data exchange
440 if( ExportStream( aStrm
, String(), nFmt
) )
442 aStrm
<< (sal_Char
) 0;
443 aStrm
.Seek( STREAM_SEEK_TO_END
);
444 // Sicherheits-Check:
445 if( aStrm
.Tell() <= (ULONG
) STRING_MAXLEN
)
447 rText
= (const sal_Char
*) aStrm
.GetData();
456 BOOL
ScImportExport::ImportStream( SvStream
& rStrm
, const String
& rBaseURL
, ULONG nFmt
)
458 if( nFmt
== FORMAT_STRING
)
460 if( ExtText2Doc( rStrm
) ) // pExtOptions auswerten
463 if( nFmt
== SOT_FORMATSTR_ID_SYLK
)
465 if( Sylk2Doc( rStrm
) )
468 if( nFmt
== SOT_FORMATSTR_ID_DIF
)
470 if( Dif2Doc( rStrm
) )
473 if( nFmt
== FORMAT_RTF
)
475 if( RTF2Doc( rStrm
, rBaseURL
) )
478 if( nFmt
== SOT_FORMATSTR_ID_LINK
)
479 return TRUE
; // Link-Import?
480 if ( nFmt
== SOT_FORMATSTR_ID_HTML
)
482 if( HTML2Doc( rStrm
, rBaseURL
) )
485 if ( nFmt
== SOT_FORMATSTR_ID_HTML_SIMPLE
)
487 MSE40HTMLClipFormatObj aMSE40ClpObj
; // needed to skip the header data
488 SvStream
* pHTML
= aMSE40ClpObj
.IsValid( rStrm
);
489 if ( pHTML
&& HTML2Doc( *pHTML
, rBaseURL
) )
497 BOOL
ScImportExport::ExportStream( SvStream
& rStrm
, const String
& rBaseURL
, ULONG nFmt
)
499 if( nFmt
== FORMAT_STRING
)
501 if( Doc2Text( rStrm
) )
504 if( nFmt
== SOT_FORMATSTR_ID_SYLK
)
506 if( Doc2Sylk( rStrm
) )
509 if( nFmt
== SOT_FORMATSTR_ID_DIF
)
511 if( Doc2Dif( rStrm
) )
514 if( nFmt
== SOT_FORMATSTR_ID_LINK
&& !bAll
)
517 if ( pDoc
->IsClipboard() )
518 aDocName
= ScGlobal::GetClipDocName();
521 SfxObjectShell
* pShell
= pDoc
->GetDocumentShell();
523 aDocName
= pShell
->GetTitle( SFX_TITLE_FULLNAME
);
526 DBG_ASSERT( aDocName
.Len(), "ClipBoard document has no name! :-/" );
530 USHORT nFlags
= SCA_VALID
| SCA_TAB_3D
;
532 aRange
.aStart
.Format( aRefName
, nFlags
, pDoc
, pDoc
->GetAddressConvention() );
535 if( aRange
.aStart
.Tab() != aRange
.aEnd
.Tab() )
536 nFlags
|= SCA_TAB2_3D
;
537 aRange
.Format( aRefName
, nFlags
, pDoc
);
539 String aAppName
= Application::GetAppName();
541 WriteUnicodeOrByteString( rStrm
, aAppName
, TRUE
);
542 WriteUnicodeOrByteString( rStrm
, aDocName
, TRUE
);
543 WriteUnicodeOrByteString( rStrm
, aRefName
, TRUE
);
544 if ( rStrm
.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE
)
545 rStrm
<< sal_Unicode(0);
547 rStrm
<< sal_Char(0);
548 return BOOL( rStrm
.GetError() == SVSTREAM_OK
);
551 if( nFmt
== SOT_FORMATSTR_ID_HTML
)
553 if( Doc2HTML( rStrm
, rBaseURL
) )
556 if( nFmt
== FORMAT_RTF
)
558 if( Doc2RTF( rStrm
) )
567 void ScImportExport::WriteUnicodeOrByteString( SvStream
& rStrm
, const String
& rString
, BOOL bZero
)
569 rtl_TextEncoding eEnc
= rStrm
.GetStreamCharSet();
570 if ( eEnc
== RTL_TEXTENCODING_UNICODE
)
572 if ( !IsEndianSwap( rStrm
) )
573 rStrm
.Write( rString
.GetBuffer(), rString
.Len() * sizeof(sal_Unicode
) );
576 const sal_Unicode
* p
= rString
.GetBuffer();
577 const sal_Unicode
* const pStop
= p
+ rString
.Len();
584 rStrm
<< sal_Unicode(0);
588 ByteString
aByteStr( rString
, eEnc
);
589 rStrm
<< aByteStr
.GetBuffer();
591 rStrm
<< sal_Char(0);
596 // This function could be replaced by endlub()
598 void ScImportExport::WriteUnicodeOrByteEndl( SvStream
& rStrm
)
600 if ( rStrm
.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE
)
601 { // same as endl() but unicode
602 switch ( rStrm
.GetLineDelimiter() )
605 rStrm
<< sal_Unicode(_CR
);
608 rStrm
<< sal_Unicode(_LF
);
611 rStrm
<< sal_Unicode(_CR
) << sal_Unicode(_LF
);
619 enum DoubledQuoteMode
621 DQM_KEEP
, // both are taken
622 DQM_ESCAPE
, // escaped quote, one is taken, one ignored
623 DQM_CONCAT
, // first is end, next is start, both ignored => strings combined
624 DQM_SEPARATE
// end one string and begin next
627 static const sal_Unicode
* lcl_ScanString( const sal_Unicode
* p
, String
& rString
,
628 sal_Unicode cStr
, DoubledQuoteMode eMode
)
630 p
++; //! jump over opening quote
635 const sal_Unicode
* p0
= p
;
644 // doubled quote char
648 p
++; // both for us (not breaking for-loop)
651 p
++; // one for us (breaking for-loop)
652 bCont
= TRUE
; // and more
656 rString
.Append( p0
, sal::static_int_cast
<xub_StrLen
>( (p
-1) - p0
) ); // first part
657 p0
= ++p
; // text of next part starts here
660 // positioned on next opening quote
663 if ( eMode
== DQM_ESCAPE
|| eMode
== DQM_SEPARATE
)
670 rString
.Append( p0
, sal::static_int_cast
<xub_StrLen
>( ((*p
|| *(p
-1) == cStr
) ? p
-1 : p
) - p0
) );
675 void lcl_UnescapeSylk( String
& rString
, SylkVersion eVersion
)
677 // Older versions didn't escape the semicolon.
678 // Older versions quoted the string and doubled embedded quotes, but not
679 // the semicolons, which was plain wrong.
680 if (eVersion
>= SYLK_OOO32
)
681 rString
.SearchAndReplaceAll( DOUBLE_SEMICOLON
, ';' );
683 rString
.SearchAndReplaceAll( DOUBLE_DOUBLEQUOTE
, '"' );
685 rString
.SearchAndReplaceAll( SYLK_LF
, _LF
);
688 static const sal_Unicode
* lcl_ScanSylkString( const sal_Unicode
* p
,
689 String
& rString
, SylkVersion eVersion
)
691 const sal_Unicode
* pStartQuote
= p
;
692 const sal_Unicode
* pEndQuote
= 0;
698 if (eVersion
>= SYLK_OOO32
)
704 p
+= 2; // escaped ';'
718 else if (*(p
+1) == ';')
724 pEndQuote
= p
; // Take all data as string.
725 rString
.Append( pStartQuote
+ 1, sal::static_int_cast
<xub_StrLen
>( pEndQuote
- pStartQuote
- 1 ) );
726 lcl_UnescapeSylk( rString
, eVersion
);
730 static const sal_Unicode
* lcl_ScanSylkFormula( const sal_Unicode
* p
,
731 String
& rString
, SylkVersion eVersion
)
733 const sal_Unicode
* pStart
= p
;
734 if (eVersion
>= SYLK_OOO32
)
747 rString
.Append( pStart
, sal::static_int_cast
<xub_StrLen
>( p
- pStart
));
748 lcl_UnescapeSylk( rString
, eVersion
);
752 // Nasty. If in old versions the formula contained a semicolon, it was
753 // quoted and embedded quotes were doubled, but semicolons were not. If
754 // there was no semicolon, it could still contain quotes and doubled
755 // embedded quotes if it was something like ="a""b", which was saved as
756 // E"a""b" as is and has to be preserved, even if older versions
757 // couldn't even load it correctly. However, theoretically another
758 // field might follow and thus the line contain a semicolon again, such
759 // as ...;E"a""b";...
760 bool bQuoted
= false;
763 // May be a quoted expression or just a string constant expression
772 break; // closing '"', had no ';' yet
776 bQuoted
= true; // ';' within quoted expression
783 p
= lcl_ScanSylkString( p
, rString
, eVersion
);
786 while (*p
&& *p
!= ';')
788 rString
.Append( pStart
, sal::static_int_cast
<xub_StrLen
>( p
- pStart
));
794 static void lcl_DoubleEscapeChar( String
& rString
, sal_Unicode cStr
)
797 while( ( n
= rString
.Search( cStr
, n
) ) != STRING_NOTFOUND
)
799 rString
.Insert( cStr
, n
);
804 static void lcl_WriteString( SvStream
& rStrm
, String
& rString
, sal_Unicode cQuote
, sal_Unicode cEsc
)
807 lcl_DoubleEscapeChar( rString
, cEsc
);
811 rString
.Insert( cQuote
, 0 );
812 rString
.Append( cQuote
);
815 ScImportExport::WriteUnicodeOrByteString( rStrm
, rString
);
818 inline void lcl_WriteSimpleString( SvStream
& rStrm
, const String
& rString
)
820 ScImportExport::WriteUnicodeOrByteString( rStrm
, rString
);
823 //////////////////////////////////////////////////////////////////////////////
826 BOOL
ScImportExport::Text2Doc( SvStream
& rStrm
)
830 SCCOL nStartCol
= aRange
.aStart
.Col();
831 SCROW nStartRow
= aRange
.aStart
.Row();
832 SCCOL nEndCol
= aRange
.aEnd
.Col();
833 SCROW nEndRow
= aRange
.aEnd
.Row();
834 ULONG nOldPos
= rStrm
.Tell();
835 if ( rStrm
.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE
)
836 rStrm
.StartReadingUnicodeText();
837 BOOL bData
= BOOL( !bSingle
);
843 ByteString aByteLine
;
845 SCROW nRow
= nStartRow
;
846 rStrm
.Seek( nOldPos
);
849 rStrm
.ReadUniOrByteStringLine( aLine
);
852 SCCOL nCol
= nStartCol
;
853 const sal_Unicode
* p
= aLine
.GetBuffer();
859 p
= lcl_ScanString( p
, aCell
, cStr
, DQM_KEEP
);
860 while( *p
&& *p
!= cSep
)
867 const sal_Unicode
* q
= p
;
868 while( *p
&& *p
!= cSep
)
870 aCell
.Assign( q
, sal::static_int_cast
<xub_StrLen
>( p
- q
) );
874 if (ValidCol(nCol
) && ValidRow(nRow
) )
878 if (nCol
>nEndCol
) nEndCol
= nCol
;
879 if (nRow
>nEndRow
) nEndRow
= nRow
;
881 if( bData
&& nCol
<= nEndCol
&& nRow
<= nEndRow
)
882 pDoc
->SetString( nCol
, nRow
, aRange
.aStart
.Tab(), aCell
);
884 else // zuviele Spalten/Zeilen
885 bOverflow
= TRUE
; // beim Import Warnung ausgeben
893 aRange
.aEnd
.SetCol( nEndCol
);
894 aRange
.aEnd
.SetRow( nEndRow
);
907 // erweiterter Ascii-Import
911 static bool lcl_PutString(
912 ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const String
& rStr
, BYTE nColFormat
,
913 SvNumberFormatter
* pFormatter
, bool bDetectNumFormat
,
914 ::utl::TransliterationWrapper
& rTransliteration
, CalendarWrapper
& rCalendar
,
915 ::utl::TransliterationWrapper
* pSecondTransliteration
, CalendarWrapper
* pSecondCalendar
)
917 bool bMultiLine
= false;
918 if ( nColFormat
== SC_COL_SKIP
|| !rStr
.Len() || !ValidCol(nCol
) || !ValidRow(nRow
) )
921 if ( nColFormat
== SC_COL_TEXT
)
925 if (pFormatter
->IsNumberFormat(rStr
, nIndex
, fDummy
))
927 // Set the format of this cell to Text.
928 sal_uInt32 nFormat
= pFormatter
->GetStandardFormat(NUMBERFORMAT_TEXT
);
929 ScPatternAttr
aNewAttrs(pDoc
->GetPool());
930 SfxItemSet
& rSet
= aNewAttrs
.GetItemSet();
931 rSet
.Put( SfxUInt32Item(ATTR_VALUE_FORMAT
, nFormat
) );
932 pDoc
->ApplyPattern(nCol
, nRow
, nTab
, aNewAttrs
);
935 pDoc
->PutCell( nCol
, nRow
, nTab
, ScBaseCell::CreateTextCell( rStr
, pDoc
) );
939 if ( nColFormat
== SC_COL_ENGLISH
)
941 //! SetString mit Extra-Flag ???
943 SvNumberFormatter
* pDocFormatter
= pDoc
->GetFormatTable();
944 sal_uInt32 nEnglish
= pDocFormatter
->GetStandardIndex(LANGUAGE_ENGLISH_US
);
946 if ( pDocFormatter
->IsNumberFormat( rStr
, nEnglish
, fVal
) )
948 // Zahlformat wird nicht auf englisch gesetzt
949 pDoc
->SetValue( nCol
, nRow
, nTab
, fVal
);
952 // sonst weiter mit SetString
954 else if ( nColFormat
!= SC_COL_STANDARD
) // Datumsformate
956 const USHORT nMaxNumberParts
= 7; // Y-M-D h:m:s.t
957 xub_StrLen nLen
= rStr
.Len();
958 xub_StrLen nStart
[nMaxNumberParts
];
959 xub_StrLen nEnd
[nMaxNumberParts
];
961 USHORT nDP
, nMP
, nYP
;
962 switch ( nColFormat
)
964 case SC_COL_YMD
: nDP
= 2; nMP
= 1; nYP
= 0; break;
965 case SC_COL_MDY
: nDP
= 1; nMP
= 0; nYP
= 2; break;
967 default: nDP
= 0; nMP
= 1; nYP
= 2; break;
972 for ( xub_StrLen nPos
=0; nPos
<nLen
&& (bInNum
||
973 nFound
<nMaxNumberParts
); nPos
++ )
975 if (bInNum
&& nFound
== 3 && nColFormat
== SC_COL_YMD
&&
976 nPos
<= nStart
[nFound
]+2 && rStr
.GetChar(nPos
) == 'T')
977 bInNum
= FALSE
; // ISO-8601: YYYY-MM-DDThh:mm...
978 else if ((((!bInNum
&& nFound
==nMP
) || (bInNum
&& nFound
==nMP
+1))
979 && ScGlobal::pCharClass
->isLetterNumeric( rStr
, nPos
))
980 || ScGlobal::pCharClass
->isDigit( rStr
, nPos
))
985 nStart
[nFound
] = nPos
;
988 nEnd
[nFound
-1] = nPos
;
996 // try to break one number (without separators) into date fields
998 xub_StrLen nDateStart
= nStart
[0];
999 xub_StrLen nDateLen
= nEnd
[0] + 1 - nDateStart
;
1001 if ( nDateLen
>= 5 && nDateLen
<= 8 &&
1002 ScGlobal::pCharClass
->isNumeric( rStr
.Copy( nDateStart
, nDateLen
) ) )
1004 // 6 digits: 2 each for day, month, year
1005 // 8 digits: 4 for year, 2 each for day and month
1006 // 5 or 7 digits: first field is shortened by 1
1008 BOOL bLongYear
= ( nDateLen
>= 7 );
1009 BOOL bShortFirst
= ( nDateLen
== 5 || nDateLen
== 7 );
1011 USHORT nFieldStart
= nDateStart
;
1012 for (USHORT nPos
=0; nPos
<3; nPos
++)
1014 USHORT nFieldEnd
= nFieldStart
+ 1; // default: 2 digits
1015 if ( bLongYear
&& nPos
== nYP
)
1016 nFieldEnd
+= 2; // 2 extra digits for long year
1017 if ( bShortFirst
&& nPos
== 0 )
1018 --nFieldEnd
; // first field shortened?
1020 nStart
[nPos
] = nFieldStart
;
1021 nEnd
[nPos
] = nFieldEnd
;
1022 nFieldStart
= nFieldEnd
+ 1;
1030 using namespace ::com::sun::star
;
1031 BOOL bSecondCal
= FALSE
;
1032 USHORT nDay
= (USHORT
) rStr
.Copy( nStart
[nDP
], nEnd
[nDP
]+1-nStart
[nDP
] ).ToInt32();
1033 USHORT nYear
= (USHORT
) rStr
.Copy( nStart
[nYP
], nEnd
[nYP
]+1-nStart
[nYP
] ).ToInt32();
1034 String aMStr
= rStr
.Copy( nStart
[nMP
], nEnd
[nMP
]+1-nStart
[nMP
] );
1035 sal_Int16 nMonth
= (sal_Int16
) aMStr
.ToInt32();
1038 static const String
aSeptCorrect( RTL_CONSTASCII_USTRINGPARAM( "SEPT" ) );
1039 static const String
aSepShortened( RTL_CONSTASCII_USTRINGPARAM( "SEP" ) );
1040 uno::Sequence
< i18n::CalendarItem
> xMonths
;
1041 sal_Int32 i
, nMonthCount
;
1042 // first test all month names from local international
1043 xMonths
= rCalendar
.getMonths();
1044 nMonthCount
= xMonths
.getLength();
1045 for (i
=0; i
<nMonthCount
&& !nMonth
; i
++)
1047 if ( rTransliteration
.isEqual( aMStr
, xMonths
[i
].FullName
) ||
1048 rTransliteration
.isEqual( aMStr
, xMonths
[i
].AbbrevName
) )
1049 nMonth
= sal::static_int_cast
<sal_Int16
>( i
+1 );
1050 else if ( i
== 8 && rTransliteration
.isEqual( aSeptCorrect
,
1051 xMonths
[i
].AbbrevName
) &&
1052 rTransliteration
.isEqual( aMStr
, aSepShortened
) )
1053 { // #102136# correct English abbreviation is SEPT,
1054 // but data mostly contains SEP only
1055 nMonth
= sal::static_int_cast
<sal_Int16
>( i
+1 );
1058 // if none found, then test english month names
1059 if ( !nMonth
&& pSecondCalendar
&& pSecondTransliteration
)
1061 xMonths
= pSecondCalendar
->getMonths();
1062 nMonthCount
= xMonths
.getLength();
1063 for (i
=0; i
<nMonthCount
&& !nMonth
; i
++)
1065 if ( pSecondTransliteration
->isEqual( aMStr
, xMonths
[i
].FullName
) ||
1066 pSecondTransliteration
->isEqual( aMStr
, xMonths
[i
].AbbrevName
) )
1068 nMonth
= sal::static_int_cast
<sal_Int16
>( i
+1 );
1071 else if ( i
== 8 && pSecondTransliteration
->isEqual(
1072 aMStr
, aSepShortened
) )
1073 { // #102136# correct English abbreviation is SEPT,
1074 // but data mostly contains SEP only
1075 nMonth
= sal::static_int_cast
<sal_Int16
>( i
+1 );
1082 SvNumberFormatter
* pDocFormatter
= pDoc
->GetFormatTable();
1084 nYear
= pDocFormatter
->ExpandTwoDigitYear( nYear
);
1086 CalendarWrapper
* pCalendar
= (bSecondCal
? pSecondCalendar
: &rCalendar
);
1087 sal_Int16 nNumMonths
= pCalendar
->getNumberOfMonthsInYear();
1088 if ( nDay
&& nMonth
&& nDay
<=31 && nMonth
<=nNumMonths
)
1091 pCalendar
->setValue( i18n::CalendarFieldIndex::DAY_OF_MONTH
, nDay
);
1092 pCalendar
->setValue( i18n::CalendarFieldIndex::MONTH
, nMonth
);
1093 pCalendar
->setValue( i18n::CalendarFieldIndex::YEAR
, nYear
);
1094 sal_Int16 nHour
, nMinute
, nSecond
, nMilli
;
1095 // #i14974# The imported value should have no fractional value, so set the
1096 // time fields to zero (ICU calendar instance defaults to current date/time)
1097 nHour
= nMinute
= nSecond
= nMilli
= 0;
1099 nHour
= (sal_Int16
) rStr
.Copy( nStart
[3], nEnd
[3]+1-nStart
[3]).ToInt32();
1101 nMinute
= (sal_Int16
) rStr
.Copy( nStart
[4], nEnd
[4]+1-nStart
[4]).ToInt32();
1103 nSecond
= (sal_Int16
) rStr
.Copy( nStart
[5], nEnd
[5]+1-nStart
[5]).ToInt32();
1106 sal_Unicode cDec
= '.';
1107 rtl::OUString
aT( &cDec
, 1);
1108 aT
+= rStr
.Copy( nStart
[6], nEnd
[6]+1-nStart
[6]);
1109 rtl_math_ConversionStatus eStatus
;
1110 double fV
= rtl::math::stringToDouble( aT
, cDec
, 0, &eStatus
, 0);
1111 if (eStatus
== rtl_math_ConversionStatus_Ok
)
1112 nMilli
= (sal_Int16
) (1000.0 * fV
+ 0.5);
1114 pCalendar
->setValue( i18n::CalendarFieldIndex::HOUR
, nHour
);
1115 pCalendar
->setValue( i18n::CalendarFieldIndex::MINUTE
, nMinute
);
1116 pCalendar
->setValue( i18n::CalendarFieldIndex::SECOND
, nSecond
);
1117 pCalendar
->setValue( i18n::CalendarFieldIndex::MILLISECOND
, nMilli
);
1118 if ( pCalendar
->isValid() )
1120 double fDiff
= DateTime(*pDocFormatter
->GetNullDate()) -
1121 pCalendar
->getEpochStart();
1122 // #i14974# must use getLocalDateTime to get the same
1123 // date values as set above
1124 double fDays
= pCalendar
->getLocalDateTime();
1127 LanguageType eLatin
, eCjk
, eCtl
;
1128 pDoc
->GetLanguage( eLatin
, eCjk
, eCtl
);
1129 LanguageType eDocLang
= eLatin
; //! which language for date formats?
1131 short nType
= (nFound
> 3 ? NUMBERFORMAT_DATETIME
: NUMBERFORMAT_DATE
);
1132 ULONG nFormat
= pDocFormatter
->GetStandardFormat( nType
, eDocLang
);
1133 // maybe there is a special format including seconds or milliseconds
1135 nFormat
= pDocFormatter
->GetStandardFormat( fDays
, nFormat
, nType
, eDocLang
);
1137 pDoc
->PutCell( nCol
, nRow
, nTab
, new ScValueCell(fDays
), nFormat
, FALSE
);
1139 return bMultiLine
; // success
1145 // Standard or date not determined -> SetString / EditCell
1146 if( rStr
.Search( _LF
) == STRING_NOTFOUND
)
1148 ScSetStringParam aParam
;
1149 aParam
.mpNumFormatter
= pFormatter
;
1150 aParam
.mbDetectNumberFormat
= bDetectNumFormat
;
1151 aParam
.mbSetTextCellFormat
= true;
1152 pDoc
->SetString( nCol
, nRow
, nTab
, rStr
, &aParam
);
1157 pDoc
->PutCell( nCol
, nRow
, nTab
, new ScEditCell( rStr
, pDoc
) );
1163 String
lcl_GetFixed( const String
& rLine
, xub_StrLen nStart
, xub_StrLen nNext
, bool& rbIsQuoted
)
1165 xub_StrLen nLen
= rLine
.Len();
1168 if ( nNext
<= nStart
)
1169 return EMPTY_STRING
;
1171 const sal_Unicode
* pStr
= rLine
.GetBuffer();
1173 xub_StrLen nSpace
= nNext
;
1174 while ( nSpace
> nStart
&& pStr
[nSpace
-1] == ' ' )
1177 rbIsQuoted
= (pStr
[nStart
] == sal_Unicode('"') && pStr
[nSpace
-1] == sal_Unicode('"'));
1179 return rLine
.Copy(nStart
+1, nSpace
-nStart
-2);
1181 return rLine
.Copy(nStart
, nSpace
-nStart
);
1184 BOOL
ScImportExport::ExtText2Doc( SvStream
& rStrm
)
1187 return Text2Doc( rStrm
);
1189 ULONG nOldPos
= rStrm
.Tell();
1190 rStrm
.Seek( STREAM_SEEK_TO_END
);
1191 ::std::auto_ptr
<ScProgress
> xProgress( new ScProgress( pDocSh
,
1192 ScGlobal::GetRscString( STR_LOAD_DOC
), rStrm
.Tell() - nOldPos
));
1193 rStrm
.Seek( nOldPos
);
1194 if ( rStrm
.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE
)
1195 rStrm
.StartReadingUnicodeText();
1197 BOOL bOld
= ScColumn::bDoubleAlloc
;
1198 ScColumn::bDoubleAlloc
= TRUE
;
1200 SCCOL nStartCol
= aRange
.aStart
.Col();
1201 SCCOL nEndCol
= aRange
.aEnd
.Col();
1202 SCROW nStartRow
= aRange
.aStart
.Row();
1203 SCTAB nTab
= aRange
.aStart
.Tab();
1205 BOOL bFixed
= pExtOptions
->IsFixedLen();
1206 const String
& rSeps
= pExtOptions
->GetFieldSeps();
1207 const sal_Unicode
* pSeps
= rSeps
.GetBuffer();
1208 BOOL bMerge
= pExtOptions
->IsMergeSeps();
1209 USHORT nInfoCount
= pExtOptions
->GetInfoCount();
1210 const xub_StrLen
* pColStart
= pExtOptions
->GetColStart();
1211 const BYTE
* pColFormat
= pExtOptions
->GetColFormat();
1212 long nSkipLines
= pExtOptions
->GetStartRow();
1214 LanguageType eDocLang
= pExtOptions
->GetLanguage();
1215 SvNumberFormatter
aNumFormatter(pDoc
->GetServiceManager(), eDocLang
);
1216 bool bDetectNumFormat
= pExtOptions
->IsDetectSpecialNumber();
1218 // For date recognition
1219 ::utl::TransliterationWrapper
aTransliteration(
1220 pDoc
->GetServiceManager(), SC_TRANSLITERATION_IGNORECASE
);
1221 aTransliteration
.loadModuleIfNeeded( eDocLang
);
1222 CalendarWrapper
aCalendar( pDoc
->GetServiceManager() );
1223 aCalendar
.loadDefaultCalendar(
1224 MsLangId::convertLanguageToLocale( eDocLang
) );
1225 ::utl::TransliterationWrapper
* pEnglishTransliteration
= NULL
;
1226 CalendarWrapper
* pEnglishCalendar
= NULL
;
1227 if ( eDocLang
!= LANGUAGE_ENGLISH_US
)
1229 pEnglishTransliteration
= new ::utl::TransliterationWrapper (
1230 pDoc
->GetServiceManager(), SC_TRANSLITERATION_IGNORECASE
);
1231 aTransliteration
.loadModuleIfNeeded( LANGUAGE_ENGLISH_US
);
1232 pEnglishCalendar
= new CalendarWrapper ( pDoc
->GetServiceManager() );
1233 pEnglishCalendar
->loadDefaultCalendar(
1234 MsLangId::convertLanguageToLocale( LANGUAGE_ENGLISH_US
) );
1237 String aLine
, aCell
;
1239 SCROW nRow
= nStartRow
;
1241 while(--nSkipLines
>0)
1243 rStrm
.ReadCsvLine( aLine
, !bFixed
, rSeps
, cStr
); // content is ignored
1244 if ( rStrm
.IsEof() )
1248 // Determine range for Undo.
1249 // TODO: we don't need this during import of a file to a new sheet or
1250 // document, could set bDetermineRange=false then.
1251 bool bDetermineRange
= true;
1253 // Row heights don't need to be adjusted on the fly if EndPaste() is called
1254 // afterwards, which happens only if bDetermineRange. This variable also
1255 // survives the toggle of bDetermineRange down at the end of the do{} loop.
1256 bool bRangeIsDetermined
= bDetermineRange
;
1258 bool bQuotedAsText
= pExtOptions
&& pExtOptions
->IsQuotedAsText();
1260 ULONG nOriginalStreamPos
= rStrm
.Tell();
1266 rStrm
.ReadCsvLine( aLine
, !bFixed
, rSeps
, cStr
);
1267 if ( rStrm
.IsEof() )
1270 xub_StrLen nLineLen
= aLine
.Len();
1271 SCCOL nCol
= nStartCol
;
1272 bool bMultiLine
= false;
1273 if ( bFixed
) // Feste Satzlaenge
1275 // Yes, the check is nCol<=MAXCOL+1, +1 because it is only an
1276 // overflow if there is really data following to be put behind
1277 // the last column, which doesn't happen if info is
1279 for ( i
=0; i
<nInfoCount
&& nCol
<= MAXCOL
+1; i
++ )
1281 BYTE nFmt
= pColFormat
[i
];
1282 if (nFmt
!= SC_COL_SKIP
) // sonst auch nCol nicht hochzaehlen
1285 bOverflow
= TRUE
; // display warning on import
1286 else if (!bDetermineRange
)
1288 xub_StrLen nStart
= pColStart
[i
];
1289 xub_StrLen nNext
= ( i
+1 < nInfoCount
) ? pColStart
[i
+1] : nLineLen
;
1290 bool bIsQuoted
= false;
1291 aCell
= lcl_GetFixed( aLine
, nStart
, nNext
, bIsQuoted
);
1292 if (bIsQuoted
&& bQuotedAsText
)
1295 bMultiLine
|= lcl_PutString(
1296 pDoc
, nCol
, nRow
, nTab
, aCell
, nFmt
,
1297 &aNumFormatter
, bDetectNumFormat
, aTransliteration
, aCalendar
,
1298 pEnglishTransliteration
, pEnglishCalendar
);
1304 else // Nach Trennzeichen suchen
1306 SCCOL nSourceCol
= 0;
1307 USHORT nInfoStart
= 0;
1308 const sal_Unicode
* p
= aLine
.GetBuffer();
1309 // Yes, the check is nCol<=MAXCOL+1, +1 because it is only an
1310 // overflow if there is really data following to be put behind
1311 // the last column, which doesn't happen if info is
1313 while (*p
&& nCol
<= MAXCOL
+1)
1315 bool bIsQuoted
= false;
1316 p
= ScImportExport::ScanNextFieldFromString( p
, aCell
, cStr
, pSeps
, bMerge
, bIsQuoted
);
1318 BYTE nFmt
= SC_COL_STANDARD
;
1319 for ( i
=nInfoStart
; i
<nInfoCount
; i
++ )
1321 if ( pColStart
[i
] == nSourceCol
+ 1 ) // pColStart ist 1-basiert
1323 nFmt
= pColFormat
[i
];
1324 nInfoStart
= i
+ 1; // ColInfos sind in Reihenfolge
1328 if ( nFmt
!= SC_COL_SKIP
)
1331 bOverflow
= TRUE
; // display warning on import
1332 else if (!bDetermineRange
)
1334 if (bIsQuoted
&& bQuotedAsText
)
1337 bMultiLine
|= lcl_PutString(
1338 pDoc
, nCol
, nRow
, nTab
, aCell
, nFmt
,
1339 &aNumFormatter
, bDetectNumFormat
, aTransliteration
,
1340 aCalendar
, pEnglishTransliteration
, pEnglishCalendar
);
1349 nEndCol
= nCol
; //! points to the next free or even MAXCOL+2
1351 if (!bDetermineRange
)
1353 if (bMultiLine
&& !bRangeIsDetermined
&& pDocSh
)
1354 pDocSh
->AdjustRowHeight( nRow
, nRow
, nTab
);
1355 xProgress
->SetStateOnPercent( rStrm
.Tell() - nOldPos
);
1358 if ( nRow
> MAXROW
)
1360 bOverflow
= TRUE
; // display warning on import
1364 // so far nRow/nEndCol pointed to the next free
1365 if (nRow
> nStartRow
)
1367 if (nEndCol
> nStartCol
)
1368 nEndCol
= ::std::min( static_cast<SCCOL
>(nEndCol
- 1), MAXCOL
);
1370 if (bDetermineRange
)
1372 aRange
.aEnd
.SetCol( nEndCol
);
1373 aRange
.aEnd
.SetRow( nRow
);
1375 if ( !mbApi
&& nStartCol
!= nEndCol
&&
1376 !pDoc
->IsBlockEmpty( nTab
, nStartCol
+ 1, nStartRow
, nEndCol
, nRow
) )
1378 ScReplaceWarnBox
aBox( pDocSh
->GetActiveDialogParent() );
1379 if ( aBox
.Execute() != RET_YES
)
1381 delete pEnglishTransliteration
;
1382 delete pEnglishCalendar
;
1387 rStrm
.Seek( nOriginalStreamPos
);
1396 bDetermineRange
= !bDetermineRange
; // toggle
1397 } while (!bDetermineRange
);
1399 ScColumn::bDoubleAlloc
= bOld
;
1400 pDoc
->DoColResize( nTab
, nStartCol
, nEndCol
, 0 );
1402 delete pEnglishTransliteration
;
1403 delete pEnglishCalendar
;
1405 xProgress
.reset(); // make room for AdjustRowHeight progress
1406 if (bRangeIsDetermined
)
1414 const sal_Unicode
* ScImportExport::ScanNextFieldFromString( const sal_Unicode
* p
,
1415 String
& rField
, sal_Unicode cStr
, const sal_Unicode
* pSeps
, bool bMergeSeps
, bool& rbIsQuoted
)
1419 if ( *p
== cStr
) // String in Anfuehrungszeichen
1422 const sal_Unicode
* p1
;
1423 p1
= p
= lcl_ScanString( p
, rField
, cStr
, DQM_ESCAPE
);
1424 while ( *p
&& !ScGlobal::UnicodeStrChr( pSeps
, *p
) )
1426 // Append remaining unquoted and undelimited data (dirty, dirty) to
1429 rField
.Append( p1
, sal::static_int_cast
<xub_StrLen
>( p
- p1
) );
1433 else // bis zum Trennzeichen
1435 const sal_Unicode
* p0
= p
;
1436 while ( *p
&& !ScGlobal::UnicodeStrChr( pSeps
, *p
) )
1438 rField
.Append( p0
, sal::static_int_cast
<xub_StrLen
>( p
- p0
) );
1442 if ( bMergeSeps
) // folgende Trennzeichen ueberspringen
1444 while ( *p
&& ScGlobal::UnicodeStrChr( pSeps
, *p
) )
1455 BOOL
ScImportExport::Doc2Text( SvStream
& rStrm
)
1459 SCCOL nStartCol
= aRange
.aStart
.Col();
1460 SCROW nStartRow
= aRange
.aStart
.Row();
1461 SCCOL nEndCol
= aRange
.aEnd
.Col();
1462 SCROW nEndRow
= aRange
.aEnd
.Row();
1464 bool bConvertLF
= (GetSystemLineEnd() != LINEEND_LF
);
1466 for (nRow
= nStartRow
; nRow
<= nEndRow
; nRow
++)
1468 if (bIncludeFiltered
|| !pDoc
->RowFiltered( nRow
, aRange
.aStart
.Tab() ))
1470 for (nCol
= nStartCol
; nCol
<= nEndCol
; nCol
++)
1473 pDoc
->GetCellType( nCol
, nRow
, aRange
.aStart
.Tab(), eType
);
1476 case CELLTYPE_FORMULA
:
1480 pDoc
->GetFormula( nCol
, nRow
, aRange
.aStart
.Tab(), aCell
, TRUE
);
1481 if( aCell
.Search( cSep
) != STRING_NOTFOUND
)
1482 lcl_WriteString( rStrm
, aCell
, cStr
, cStr
);
1484 lcl_WriteSimpleString( rStrm
, aCell
);
1488 pDoc
->GetString( nCol
, nRow
, aRange
.aStart
.Tab(), aCell
);
1490 bool bMultiLineText
= ( aCell
.Search( _LF
) != STRING_NOTFOUND
);
1491 if( bMultiLineText
)
1493 if( mExportTextOptions
.meNewlineConversion
== ScExportTextOptions::ToSpace
)
1494 aCell
.SearchAndReplaceAll( _LF
, ' ' );
1495 else if ( mExportTextOptions
.meNewlineConversion
== ScExportTextOptions::ToSystem
&& bConvertLF
)
1496 aCell
.ConvertLineEnd();
1499 if( mExportTextOptions
.mcSeparatorConvertTo
&& cSep
)
1500 aCell
.SearchAndReplaceAll( cSep
, mExportTextOptions
.mcSeparatorConvertTo
);
1502 if( mExportTextOptions
.mbAddQuotes
&& ( aCell
.Search( cSep
) != STRING_NOTFOUND
) )
1503 lcl_WriteString( rStrm
, aCell
, cStr
, cStr
);
1505 lcl_WriteSimpleString( rStrm
, aCell
);
1509 case CELLTYPE_VALUE
:
1511 pDoc
->GetString( nCol
, nRow
, aRange
.aStart
.Tab(), aCell
);
1512 lcl_WriteSimpleString( rStrm
, aCell
);
1520 pDoc
->GetString( nCol
, nRow
, aRange
.aStart
.Tab(), aCell
);
1522 bool bMultiLineText
= ( aCell
.Search( _LF
) != STRING_NOTFOUND
);
1523 if( bMultiLineText
)
1525 if( mExportTextOptions
.meNewlineConversion
== ScExportTextOptions::ToSpace
)
1526 aCell
.SearchAndReplaceAll( _LF
, ' ' );
1527 else if ( mExportTextOptions
.meNewlineConversion
== ScExportTextOptions::ToSystem
&& bConvertLF
)
1528 aCell
.ConvertLineEnd();
1531 if( mExportTextOptions
.mcSeparatorConvertTo
&& cSep
)
1532 aCell
.SearchAndReplaceAll( cSep
, mExportTextOptions
.mcSeparatorConvertTo
);
1534 if( mExportTextOptions
.mbAddQuotes
&& ( aCell
.Search( cSep
) != STRING_NOTFOUND
) )
1535 lcl_WriteString( rStrm
, aCell
, cStr
, cStr
);
1537 lcl_WriteSimpleString( rStrm
, aCell
);
1540 if( nCol
< nEndCol
)
1541 lcl_WriteSimpleString( rStrm
, String(cSep
) );
1543 // if( nRow < nEndRow )
1544 WriteUnicodeOrByteEndl( rStrm
);
1545 if( rStrm
.GetError() != SVSTREAM_OK
)
1547 if( nSizeLimit
&& rStrm
.Tell() > nSizeLimit
)
1552 return BOOL( rStrm
.GetError() == SVSTREAM_OK
);
1556 BOOL
ScImportExport::Sylk2Doc( SvStream
& rStrm
)
1559 BOOL bMyDoc
= FALSE
;
1560 SylkVersion eVersion
= SYLK_OTHER
;
1562 // US-English separators for StringToDouble
1563 sal_Unicode cDecSep
= '.';
1564 sal_Unicode cGrpSep
= ',';
1566 SCCOL nStartCol
= aRange
.aStart
.Col();
1567 SCROW nStartRow
= aRange
.aStart
.Row();
1568 SCCOL nEndCol
= aRange
.aEnd
.Col();
1569 SCROW nEndRow
= aRange
.aEnd
.Row();
1570 ULONG nOldPos
= rStrm
.Tell();
1571 BOOL bData
= BOOL( !bSingle
);
1581 ByteString aByteLine
;
1582 SCCOL nCol
= nStartCol
;
1583 SCROW nRow
= nStartRow
;
1586 rStrm
.Seek( nOldPos
);
1590 rStrm
.ReadLine( aByteLine
);
1591 aLine
= String( aByteLine
, rStrm
.GetStreamCharSet() );
1594 const sal_Unicode
* p
= aLine
.GetBuffer();
1595 sal_Unicode cTag
= *p
++;
1596 if( cTag
== 'C' ) // Content
1602 sal_Unicode ch
= *p
++;
1603 ch
= ScGlobal::ToUpperAlpha( ch
);
1607 nCol
= static_cast<SCCOL
>(String( p
).ToInt32()) + nStartCol
- 1;
1610 nRow
= String( p
).ToInt32() + nStartRow
- 1;
1613 nRefCol
= static_cast<SCCOL
>(String( p
).ToInt32()) + nStartCol
- 1;
1616 nRefRow
= String( p
).ToInt32() + nStartRow
- 1;
1621 ( nCol
< nStartCol
|| nCol
> nEndCol
1622 || nRow
< nStartRow
|| nRow
> nEndRow
1623 || nCol
> MAXCOL
|| nRow
> MAXROW
) )
1627 if( nRow
> nEndRow
)
1629 if( nCol
> nEndCol
)
1638 p
= lcl_ScanSylkString( p
, aText
, eVersion
);
1642 const sal_Unicode
* q
= p
;
1643 while( *q
&& *q
!= ';' )
1645 if ( !(*q
== ';' && *(q
+1) == 'I') )
1646 { // don't ignore value
1649 pDoc
->PutCell( nCol
, nRow
, aRange
.aStart
.Tab(),
1650 ScBaseCell::CreateTextCell( aText
, pDoc
),
1655 double fVal
= rtl_math_uStringToDouble( p
,
1656 aLine
.GetBuffer() + aLine
.Len(),
1657 cDecSep
, cGrpSep
, NULL
, NULL
);
1658 pDoc
->SetValue( nCol
, nRow
, aRange
.aStart
.Tab(), fVal
);
1668 if ( nRefCol
< nCol
)
1670 if ( nRefRow
< nRow
)
1674 if( nRefRow
> nEndRow
)
1676 if( nRefCol
> nEndCol
)
1680 if( !bMyDoc
|| !bData
)
1683 p
= lcl_ScanSylkFormula( p
, aText
, eVersion
);
1684 ScAddress
aPos( nCol
, nRow
, aRange
.aStart
.Tab() );
1685 /* FIXME: do we want GRAM_ODFF_A1 instead? At the
1686 * end it probably should be GRAM_ODFF_R1C1, since
1687 * R1C1 is what Excel writes in SYLK. */
1688 const formula::FormulaGrammar::Grammar eGrammar
= formula::FormulaGrammar::GRAM_PODF_A1
;
1689 ScCompiler
aComp( pDoc
, aPos
);
1690 aComp
.SetGrammar(eGrammar
);
1691 ScTokenArray
* pCode
= aComp
.CompileString( aText
);
1695 aMark
.SelectTable( aPos
.Tab(), TRUE
);
1696 pDoc
->InsertMatrixFormula( nCol
, nRow
, nRefCol
,
1697 nRefRow
, aMark
, EMPTY_STRING
, pCode
);
1701 ScFormulaCell
* pFCell
= new ScFormulaCell(
1702 pDoc
, aPos
, pCode
, eGrammar
, MM_NONE
);
1703 pDoc
->PutCell( aPos
, pFCell
);
1705 delete pCode
; // ctor/InsertMatrixFormula did copy TokenArray
1709 while( *p
&& *p
!= ';' )
1715 else if( cTag
== 'F' ) // Format
1719 sal_Int32 nFormat
= -1;
1722 sal_Unicode ch
= *p
++;
1723 ch
= ScGlobal::ToUpperAlpha( ch
);
1727 nCol
= static_cast<SCCOL
>(String( p
).ToInt32()) + nStartCol
- 1;
1730 nRow
= String( p
).ToInt32() + nStartRow
- 1;
1735 // F;P<n> sets format code of P;P<code> at
1736 // current position, or at ;X;Y if specified.
1737 // Note that ;X;Y may appear after ;P
1738 const sal_Unicode
* p0
= p
;
1739 while( *p
&& *p
!= ';' )
1741 String
aNumber( p0
, sal::static_int_cast
<xub_StrLen
>( p
- p0
) );
1742 nFormat
= aNumber
.ToInt32();
1746 while( *p
&& *p
!= ';' )
1753 if( nRow
> nEndRow
)
1755 if( nCol
> nEndCol
)
1758 if ( 0 <= nFormat
&& nFormat
< aFormats
.Count() )
1760 ULONG nKey
= aFormats
[(USHORT
)nFormat
];
1761 pDoc
->ApplyAttr( nCol
, nRow
, aRange
.aStart
.Tab(),
1762 SfxUInt32Item( ATTR_VALUE_FORMAT
, nKey
) );
1765 else if( cTag
== 'P' )
1767 if ( bData
&& *p
== ';' && *(p
+1) == 'P' )
1769 String
aCode( p
+2 );
1770 // unescape doubled semicolons
1771 xub_StrLen nPos
= 0;
1772 String
aSemicolon( RTL_CONSTASCII_USTRINGPARAM(";;"));
1773 while ( (nPos
= aCode
.Search( aSemicolon
, nPos
)) != STRING_NOTFOUND
)
1774 aCode
.Erase( nPos
++, 1 );
1775 // get rid of Xcl escape characters
1777 while ( (nPos
= aCode
.Search( sal_Unicode(0x1b), nPos
)) != STRING_NOTFOUND
)
1778 aCode
.Erase( nPos
, 1 );
1779 xub_StrLen nCheckPos
;
1782 pDoc
->GetFormatTable()->PutandConvertEntry(
1783 aCode
, nCheckPos
, nType
, nKey
, LANGUAGE_ENGLISH_US
,
1787 aFormats
.Insert( nKey
, aFormats
.Count() );
1790 else if( cTag
== 'I' && *p
== 'D' )
1792 aLine
.Erase( 0, 4 );
1793 if (aLine
.EqualsAscii( "CALCOOO32" ))
1794 eVersion
= SYLK_OOO32
;
1795 else if (aLine
.EqualsAscii( "SCALC3" ))
1796 eVersion
= SYLK_SCALC3
;
1797 bMyDoc
= (eVersion
<= SYLK_OWN
);
1799 else if( cTag
== 'E' ) // Ende
1804 aRange
.aEnd
.SetCol( nEndCol
);
1805 aRange
.aEnd
.SetRow( nEndRow
);
1818 BOOL
ScImportExport::Doc2Sylk( SvStream
& rStrm
)
1822 SCCOL nStartCol
= aRange
.aStart
.Col();
1823 SCROW nStartRow
= aRange
.aStart
.Row();
1824 SCCOL nEndCol
= aRange
.aEnd
.Col();
1825 SCROW nEndRow
= aRange
.aEnd
.Row();
1828 lcl_WriteSimpleString( rStrm
,
1829 String( RTL_CONSTASCII_USTRINGPARAM( "ID;PCALCOOO32")));
1830 WriteUnicodeOrByteEndl( rStrm
);
1832 for (nRow
= nStartRow
; nRow
<= nEndRow
; nRow
++)
1834 for (nCol
= nStartCol
; nCol
<= nEndCol
; nCol
++)
1839 SCROW r
= nRow
- nStartRow
+ 1;
1840 SCCOL c
= nCol
- nStartCol
+ 1;
1842 pDoc
->GetCell( nCol
, nRow
, aRange
.aStart
.Tab(), pCell
);
1843 CellType eType
= (pCell
? pCell
->GetCellType() : CELLTYPE_NONE
);
1846 case CELLTYPE_FORMULA
:
1848 if( pDoc
->HasValueData( nCol
, nRow
, aRange
.aStart
.Tab()) )
1853 case CELLTYPE_VALUE
:
1855 pDoc
->GetValue( nCol
, nRow
, aRange
.aStart
.Tab(), nVal
);
1857 aValStr
= ::rtl::math::doubleToUString( nVal
,
1858 rtl_math_StringFormat_Automatic
,
1859 rtl_math_DecimalPlaces_Max
, '.', TRUE
);
1861 aBufStr
.AssignAscii(RTL_CONSTASCII_STRINGPARAM( "C;X" ));
1862 aBufStr
+= String::CreateFromInt32( c
);
1863 aBufStr
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";Y" ));
1864 aBufStr
+= String::CreateFromInt32( r
);
1865 aBufStr
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";K" ));
1867 lcl_WriteSimpleString( rStrm
, aBufStr
);
1870 case CELLTYPE_STRING
:
1873 pDoc
->GetString( nCol
, nRow
, aRange
.aStart
.Tab(), aCellStr
);
1874 aCellStr
.SearchAndReplaceAll( _LF
, SYLK_LF
);
1876 aBufStr
.AssignAscii(RTL_CONSTASCII_STRINGPARAM( "C;X" ));
1877 aBufStr
+= String::CreateFromInt32( c
);
1878 aBufStr
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";Y" ));
1879 aBufStr
+= String::CreateFromInt32( r
);
1880 aBufStr
.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ";K" ));
1881 lcl_WriteSimpleString( rStrm
, aBufStr
);
1882 lcl_WriteString( rStrm
, aCellStr
, '"', ';' );
1887 const ScFormulaCell
* pFCell
=
1888 static_cast<const ScFormulaCell
*>(pCell
);
1889 switch ( pFCell
->GetMatrixFlag() )
1895 pFCell
->GetFormula( aCellStr
,formula::FormulaGrammar::GRAM_PODF_A1
);
1896 /* FIXME: do we want GRAM_ODFF_A1 instead? At
1897 * the end it probably should be
1898 * GRAM_ODFF_R1C1, since R1C1 is what Excel
1899 * writes in SYLK. */
1901 if ( pFCell
->GetMatrixFlag() != MM_NONE
&&
1902 aCellStr
.Len() > 2 &&
1903 aCellStr
.GetChar(0) == '{' &&
1904 aCellStr
.GetChar(aCellStr
.Len()-1) == '}' )
1905 { // cut off matrix {} characters
1906 aCellStr
.Erase(aCellStr
.Len()-1,1);
1907 aCellStr
.Erase(0,1);
1909 if ( aCellStr
.GetChar(0) == '=' )
1910 aCellStr
.Erase(0,1);
1912 switch ( pFCell
->GetMatrixFlag() )
1915 { // diff expression with 'M' M$-extension
1918 pFCell
->GetMatColsRows( nC
, nR
);
1921 aPrefix
.AssignAscii( RTL_CONSTASCII_STRINGPARAM( ";R" ) );
1922 aPrefix
+= String::CreateFromInt32( nR
);
1923 aPrefix
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ";C" ) );
1924 aPrefix
+= String::CreateFromInt32( nC
);
1925 aPrefix
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ";M" ) );
1929 { // diff expression with 'I' M$-extension
1931 pFCell
->GetMatrixOrigin( aPos
);
1932 aPrefix
.AssignAscii( RTL_CONSTASCII_STRINGPARAM( ";I;R" ) );
1933 aPrefix
+= String::CreateFromInt32( aPos
.Row() - nStartRow
+ 1 );
1934 aPrefix
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ";C" ) );
1935 aPrefix
+= String::CreateFromInt32( aPos
.Col() - nStartCol
+ 1 );
1939 // formula Expression
1940 aPrefix
.AssignAscii( RTL_CONSTASCII_STRINGPARAM( ";E" ) );
1942 lcl_WriteSimpleString( rStrm
, aPrefix
);
1943 if ( aCellStr
.Len() )
1944 lcl_WriteString( rStrm
, aCellStr
, 0, ';' );
1946 WriteUnicodeOrByteEndl( rStrm
);
1951 // added to avoid warnings
1956 lcl_WriteSimpleString( rStrm
, String( 'E' ) );
1957 WriteUnicodeOrByteEndl( rStrm
);
1958 return BOOL( rStrm
.GetError() == SVSTREAM_OK
);
1962 BOOL
ScImportExport::Doc2HTML( SvStream
& rStrm
, const String
& rBaseURL
)
1964 // CharSet is ignored in ScExportHTML, read from Load/Save HTML options
1965 ScFormatFilter::Get().ScExportHTML( rStrm
, rBaseURL
, pDoc
, aRange
, RTL_TEXTENCODING_DONTKNOW
, bAll
,
1966 aStreamPath
, aNonConvertibleChars
);
1967 return BOOL( rStrm
.GetError() == SVSTREAM_OK
);
1970 BOOL
ScImportExport::Doc2RTF( SvStream
& rStrm
)
1972 // CharSet is ignored in ScExportRTF
1973 ScFormatFilter::Get().ScExportRTF( rStrm
, pDoc
, aRange
, RTL_TEXTENCODING_DONTKNOW
);
1974 return BOOL( rStrm
.GetError() == SVSTREAM_OK
);
1978 BOOL
ScImportExport::Doc2Dif( SvStream
& rStrm
)
1980 // for DIF in the clipboard, IBM_850 is always used
1981 ScFormatFilter::Get().ScExportDif( rStrm
, pDoc
, aRange
, RTL_TEXTENCODING_IBM_850
);
1986 BOOL
ScImportExport::Dif2Doc( SvStream
& rStrm
)
1988 SCTAB nTab
= aRange
.aStart
.Tab();
1989 ScDocument
* pImportDoc
= new ScDocument( SCDOCMODE_UNDO
);
1990 pImportDoc
->InitUndo( pDoc
, nTab
, nTab
);
1992 // for DIF in the clipboard, IBM_850 is always used
1993 ScFormatFilter::Get().ScImportDif( rStrm
, pImportDoc
, aRange
.aStart
, RTL_TEXTENCODING_IBM_850
);
1997 pImportDoc
->GetCellArea( nTab
, nEndCol
, nEndRow
);
1998 // #131247# if there are no cells in the imported content, nEndCol/nEndRow may be before the start
1999 if ( nEndCol
< aRange
.aStart
.Col() )
2000 nEndCol
= aRange
.aStart
.Col();
2001 if ( nEndRow
< aRange
.aStart
.Row() )
2002 nEndRow
= aRange
.aStart
.Row();
2003 aRange
.aEnd
= ScAddress( nEndCol
, nEndRow
, nTab
);
2005 BOOL bOk
= StartPaste();
2008 USHORT nFlags
= IDF_ALL
& ~IDF_STYLES
;
2009 pDoc
->DeleteAreaTab( aRange
, nFlags
);
2010 pImportDoc
->CopyToDocument( aRange
, nFlags
, FALSE
, pDoc
);
2020 BOOL
ScImportExport::RTF2Doc( SvStream
& rStrm
, const String
& rBaseURL
)
2022 ScEEAbsImport
*pImp
= ScFormatFilter::Get().CreateRTFImport( pDoc
, aRange
);
2025 pImp
->Read( rStrm
, rBaseURL
);
2026 aRange
= pImp
->GetRange();
2028 BOOL bOk
= StartPaste();
2031 USHORT nFlags
= IDF_ALL
& ~IDF_STYLES
;
2032 pDoc
->DeleteAreaTab( aRange
, nFlags
);
2033 pImp
->WriteToDocument();
2041 BOOL
ScImportExport::HTML2Doc( SvStream
& rStrm
, const String
& rBaseURL
)
2043 ScEEAbsImport
*pImp
= ScFormatFilter::Get().CreateHTMLImport( pDoc
, rBaseURL
, aRange
, TRUE
);
2046 pImp
->Read( rStrm
, rBaseURL
);
2047 aRange
= pImp
->GetRange();
2049 BOOL bOk
= StartPaste();
2052 // ScHTMLImport may call ScDocument::InitDrawLayer, resulting in
2053 // a Draw Layer but no Draw View -> create Draw Layer and View here
2055 pDocSh
->MakeDrawLayer();
2057 USHORT nFlags
= IDF_ALL
& ~IDF_STYLES
;
2058 pDoc
->DeleteAreaTab( aRange
, nFlags
);
2059 pImp
->WriteToDocument();
2066 #define RETURN_ERROR { return eERR_INTERN; }
2067 class ScFormatFilterMissing
: public ScFormatFilterPlugin
{
2069 ScFormatFilterMissing()
2071 OSL_ASSERT ("Missing file filters");
2073 virtual FltError
ScImportLotus123( SfxMedium
&, ScDocument
*, CharSet
) RETURN_ERROR
2074 virtual FltError
ScImportQuattroPro( SfxMedium
&, ScDocument
* ) RETURN_ERROR
2075 virtual FltError
ScImportExcel( SfxMedium
&, ScDocument
*, const EXCIMPFORMAT
) RETURN_ERROR
2076 virtual FltError
ScImportStarCalc10( SvStream
&, ScDocument
* ) RETURN_ERROR
2077 virtual FltError
ScImportDif( SvStream
&, ScDocument
*, const ScAddress
&,
2078 const CharSet
, UINT32
) RETURN_ERROR
2079 virtual FltError
ScImportRTF( SvStream
&, const String
&, ScDocument
*, ScRange
& ) RETURN_ERROR
2080 virtual FltError
ScImportHTML( SvStream
&, const String
&, ScDocument
*, ScRange
&, double, BOOL
, SvNumberFormatter
*, bool ) RETURN_ERROR
2082 virtual ScEEAbsImport
*CreateRTFImport( ScDocument
*, const ScRange
& ) { return NULL
; }
2083 virtual ScEEAbsImport
*CreateHTMLImport( ScDocument
*, const String
&, const ScRange
&, BOOL
) { return NULL
; }
2084 virtual String
GetHTMLRangeNameList( ScDocument
*, const String
& ) { return String(); }
2086 #if ENABLE_LOTUS123_EXPORT
2087 virtual FltError
ScExportLotus123( SvStream
&, ScDocument
*, ExportFormatLotus
, CharSet
) RETURN_ERROR
2089 virtual FltError
ScExportExcel5( SfxMedium
&, ScDocument
*, ExportFormatExcel
, CharSet
) RETURN_ERROR
2090 virtual FltError
ScExportDif( SvStream
&, ScDocument
*, const ScAddress
&, const CharSet
, UINT32
) RETURN_ERROR
2091 virtual FltError
ScExportDif( SvStream
&, ScDocument
*, const ScRange
&, const CharSet
, UINT32
) RETURN_ERROR
2092 virtual FltError
ScExportHTML( SvStream
&, const String
&, ScDocument
*, const ScRange
&, const CharSet
, BOOL
,
2093 const String
&, String
& ) RETURN_ERROR
2094 virtual FltError
ScExportRTF( SvStream
&, ScDocument
*, const ScRange
&, const CharSet
) RETURN_ERROR
2097 extern "C" { static void SAL_CALL
thisModule() {} }
2098 typedef ScFormatFilterPlugin
* (*FilterFn
)(void);
2099 ScFormatFilterPlugin
&ScFormatFilter::Get()
2101 static ScFormatFilterPlugin
*plugin
;
2106 static ::osl::Module aModule
;
2107 if ( aModule
.loadRelative( &thisModule
,
2108 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SVLIBRARY( "scfilt" ) ) ) ) )
2110 oslGenericFunction fn
= aModule
.getFunctionSymbol( ::rtl::OUString::createFromAscii( "ScFilterCreate" ) );
2112 plugin
= reinterpret_cast<FilterFn
>(fn
)();
2115 plugin
= new ScFormatFilterMissing();