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 <document.hxx>
22 #include <formulacell.hxx>
23 #include <globstr.hrc>
24 #include <scresid.hxx>
26 #include <progress.hxx>
27 #include <rtl/tencinfo.h>
29 #include <cellvalue.hxx>
30 #include <rtl/strbuf.hxx>
31 #include <osl/diagnose.h>
32 #include <formula/errorcodes.hxx>
33 #include <tools/stream.hxx>
35 void ScFormatFilterPluginImpl::ScExportDif( SvStream
& rStream
, ScDocument
* pDoc
,
36 const ScAddress
& rOutPos
, const rtl_TextEncoding eNach
)
40 pDoc
->GetTableArea( rOutPos
.Tab(), nEndCol
, nEndRow
);
41 ScAddress
aEnd( nEndCol
, nEndRow
, rOutPos
.Tab() );
42 ScAddress
aStart( rOutPos
);
44 aStart
.PutInOrder( aEnd
);
46 ScExportDif( rStream
, pDoc
, ScRange( aStart
, aEnd
), eNach
);
49 void ScFormatFilterPluginImpl::ScExportDif( SvStream
& rOut
, ScDocument
* pDoc
,
50 const ScRange
&rRange
, const rtl_TextEncoding eCharSet
)
52 OSL_ENSURE( rRange
.aStart
<= rRange
.aEnd
, "*ScExportDif(): Range not sorted!" );
53 OSL_ENSURE( rRange
.aStart
.Tab() == rRange
.aEnd
.Tab(),
54 "ScExportDif(): only one table please!" );
56 const rtl_TextEncoding eStreamCharSet
= rOut
.GetStreamCharSet();
57 if ( eStreamCharSet
!= eCharSet
)
58 rOut
.SetStreamCharSet( eCharSet
);
60 sal_Unicode
cStrDelim('"');
61 OString aStrDelimEncoded
; // only used if not Unicode
62 OUString aStrDelimDecoded
; // only used if context encoding
63 bool bContextOrNotAsciiEncoding
;
64 if ( eCharSet
== RTL_TEXTENCODING_UNICODE
)
66 rOut
.StartWritingUnicodeText();
67 bContextOrNotAsciiEncoding
= false;
71 aStrDelimEncoded
= OString(&cStrDelim
, 1, eCharSet
);
72 rtl_TextEncodingInfo aInfo
;
73 aInfo
.StructSize
= sizeof(aInfo
);
74 if ( rtl_getTextEncodingInfo( eCharSet
, &aInfo
) )
76 bContextOrNotAsciiEncoding
=
77 (((aInfo
.Flags
& RTL_TEXTENCODING_INFO_CONTEXT
) != 0) ||
78 ((aInfo
.Flags
& RTL_TEXTENCODING_INFO_ASCII
) == 0));
79 if ( bContextOrNotAsciiEncoding
)
80 aStrDelimDecoded
= OStringToOUString(aStrDelimEncoded
, eCharSet
);
83 bContextOrNotAsciiEncoding
= false;
86 const sal_Char p2DoubleQuotes_LF
[] = "\"\"\n";
87 const sal_Char pSpecDataType_LF
[] = "-1,0\n";
88 const sal_Char pEmptyData
[] = "1,0\n\"\"\n";
89 const sal_Char pStringData
[] = "1,0\n";
90 const sal_Char pNumData
[] = "0,";
91 const sal_Char pNumDataERROR
[] = "0,0\nERROR\n";
95 SCCOL nEndCol
= rRange
.aEnd
.Col();
96 SCROW nEndRow
= rRange
.aEnd
.Row();
97 SCCOL nNumCols
= nEndCol
- rRange
.aStart
.Col() + 1;
98 SCROW nNumRows
= nEndRow
- rRange
.aStart
.Row() + 1;
99 SCTAB nTab
= rRange
.aStart
.Tab();
101 ScProgress
aPrgrsBar( pDoc
->GetDocumentShell(), ScResId( STR_LOAD_DOC
), nNumRows
, true );
103 aPrgrsBar
.SetState( 0 );
106 OSL_ENSURE( pDoc
->HasTable( nTab
), "*ScExportDif(): Table not existent!" );
108 aOS
.append(pKeyTABLE
);
109 aOS
.append("\n0,1\n\"");
111 pDoc
->GetName( nTab
, aString
);
114 rOut
.WriteUnicodeOrByteText(aOS
.makeStringAndClear());
117 aOS
.append(pKeyVECTORS
);
119 aOS
.append(static_cast<sal_Int32
>(nNumCols
));
121 aOS
.append(p2DoubleQuotes_LF
);
122 rOut
.WriteUnicodeOrByteText(aOS
.makeStringAndClear());
125 aOS
.append(pKeyTUPLES
);
127 aOS
.append(static_cast<sal_Int32
>(nNumRows
));
129 aOS
.append(p2DoubleQuotes_LF
);
130 rOut
.WriteUnicodeOrByteText(aOS
.makeStringAndClear());
133 aOS
.append(pKeyDATA
);
134 aOS
.append("\n0,0\n");
135 aOS
.append(p2DoubleQuotes_LF
);
136 rOut
.WriteUnicodeOrByteText(aOS
.makeStringAndClear());
141 for( nRowCnt
= rRange
.aStart
.Row() ; nRowCnt
<= nEndRow
; nRowCnt
++ )
143 assert( aOS
.isEmpty() && "aOS should be empty");
144 aOS
.append(pSpecDataType_LF
);
147 rOut
.WriteUnicodeOrByteText(aOS
.makeStringAndClear());
148 for( nColCnt
= rRange
.aStart
.Col() ; nColCnt
<= nEndCol
; nColCnt
++ )
150 assert( aOS
.isEmpty() && "aOS should be empty");
151 bool bWriteStringData
= false;
152 ScRefCellValue
aCell(*pDoc
, ScAddress(nColCnt
, nRowCnt
, nTab
));
154 switch (aCell
.meType
)
157 aOS
.append(pEmptyData
);
160 aOS
.append(pNumData
);
161 pDoc
->GetInputString( nColCnt
, nRowCnt
, nTab
, aString
);
166 case CELLTYPE_STRING
:
167 aString
= aCell
.getString(pDoc
);
168 bWriteStringData
= true;
170 case CELLTYPE_FORMULA
:
171 if (aCell
.mpFormula
->GetErrCode() != FormulaError::NONE
)
172 aOS
.append(pNumDataERROR
);
173 else if (aCell
.mpFormula
->IsValue())
175 aOS
.append(pNumData
);
176 pDoc
->GetInputString( nColCnt
, nRowCnt
, nTab
, aString
);
182 aString
= aCell
.mpFormula
->GetString().getString();
183 bWriteStringData
= true;
190 if ( !bWriteStringData
)
191 rOut
.WriteUnicodeOrByteText(aOS
.makeStringAndClear());
194 // for an explanation why this complicated, see
195 // sc/source/ui/docsh.cxx:ScDocShell::AsciiSave()
196 // In fact we should create a common method if this would be
197 // needed just one more time...
198 assert( aOS
.isEmpty() && "aOS should be empty");
199 OUString aTmpStr
= aString
;
200 aOS
.append(pStringData
);
201 rOut
.WriteUnicodeOrByteText(aOS
.makeStringAndClear(), eCharSet
);
202 if ( eCharSet
== RTL_TEXTENCODING_UNICODE
)
204 sal_Int32 nPos
= aTmpStr
.indexOf( cStrDelim
);
207 aTmpStr
= aTmpStr
.replaceAt( nPos
, 0, OUString(cStrDelim
) );
208 nPos
= aTmpStr
.indexOf( cStrDelim
, nPos
+2 );
210 rOut
.WriteUniOrByteChar( cStrDelim
, eCharSet
);
211 write_uInt16s_FromOUString(rOut
, aTmpStr
);
212 rOut
.WriteUniOrByteChar( cStrDelim
, eCharSet
);
214 else if ( bContextOrNotAsciiEncoding
)
217 OString aStrEnc
= OUStringToOString(aTmpStr
, eCharSet
);
219 OUString aStrDec
= OStringToOUString(aStrEnc
, eCharSet
);
220 // search on re-decoded string
221 sal_Int32 nPos
= aStrDec
.indexOf(aStrDelimDecoded
);
224 OUStringBuffer
aBuf(aStrDec
);
225 aBuf
.insert(nPos
, aStrDelimDecoded
);
226 aStrDec
= aBuf
.makeStringAndClear();
227 nPos
= aStrDec
.indexOf(
228 aStrDelimDecoded
, nPos
+1+aStrDelimDecoded
.getLength());
230 // write byte re-encoded
231 rOut
.WriteUniOrByteChar( cStrDelim
, eCharSet
);
232 rOut
.WriteUnicodeOrByteText( aStrDec
, eCharSet
);
233 rOut
.WriteUniOrByteChar( cStrDelim
, eCharSet
);
237 OString aStrEnc
= OUStringToOString(aTmpStr
, eCharSet
);
238 // search on encoded string
239 sal_Int32 nPos
= aStrEnc
.indexOf(aStrDelimEncoded
);
242 OStringBuffer
aBuf(aStrEnc
);
243 aBuf
.insert(nPos
, aStrDelimEncoded
);
244 aStrEnc
= aBuf
.makeStringAndClear();
245 nPos
= aStrEnc
.indexOf(
246 aStrDelimEncoded
, nPos
+1+aStrDelimEncoded
.getLength());
248 // write byte encoded
249 rOut
.WriteBytes(aStrDelimEncoded
.getStr(), aStrDelimEncoded
.getLength());
250 rOut
.WriteBytes(aStrEnc
.getStr(), aStrEnc
.getLength());
251 rOut
.WriteBytes(aStrDelimEncoded
.getStr(), aStrDelimEncoded
.getLength());
253 rOut
.WriteUniOrByteChar( '\n', eCharSet
);
256 aPrgrsBar
.SetState( nRowCnt
);
259 assert( aOS
.isEmpty() && "aOS should be empty");
260 aOS
.append(pSpecDataType_LF
);
263 rOut
.WriteUnicodeOrByteText(aOS
.makeStringAndClear());
265 // restore original value
266 rOut
.SetStreamCharSet( eStreamCharSet
);
269 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */