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>
23 #include <formulacell.hxx>
24 #include <globstr.hrc>
25 #include <scresid.hxx>
27 #include <progress.hxx>
28 #include <rtl/tencinfo.h>
30 #include <cellvalue.hxx>
31 #include <rtl/strbuf.hxx>
32 #include <osl/diagnose.h>
33 #include <formula/errorcodes.hxx>
34 #include <tools/stream.hxx>
36 void ScFormatFilterPluginImpl::ScExportDif( SvStream
& rStream
, ScDocument
* pDoc
,
37 const ScAddress
& rOutPos
, const rtl_TextEncoding eNach
)
41 pDoc
->GetTableArea( rOutPos
.Tab(), nEndCol
, nEndRow
);
42 ScAddress
aEnd( nEndCol
, nEndRow
, rOutPos
.Tab() );
43 ScAddress
aStart( rOutPos
);
45 aStart
.PutInOrder( aEnd
);
47 ScExportDif( rStream
, pDoc
, ScRange( aStart
, aEnd
), eNach
);
50 void ScFormatFilterPluginImpl::ScExportDif( SvStream
& rOut
, ScDocument
* pDoc
,
51 const ScRange
&rRange
, const rtl_TextEncoding eCharSet
)
53 OSL_ENSURE( rRange
.aStart
<= rRange
.aEnd
, "*ScExportDif(): Range not sorted!" );
54 OSL_ENSURE( rRange
.aStart
.Tab() == rRange
.aEnd
.Tab(),
55 "ScExportDif(): only one table please!" );
57 const rtl_TextEncoding eStreamCharSet
= rOut
.GetStreamCharSet();
58 if ( eStreamCharSet
!= eCharSet
)
59 rOut
.SetStreamCharSet( eCharSet
);
61 sal_Unicode
cStrDelim('"');
62 OString aStrDelimEncoded
; // only used if not Unicode
63 OUString aStrDelimDecoded
; // only used if context encoding
64 bool bContextOrNotAsciiEncoding
;
65 if ( eCharSet
== RTL_TEXTENCODING_UNICODE
)
67 rOut
.StartWritingUnicodeText();
68 bContextOrNotAsciiEncoding
= false;
72 aStrDelimEncoded
= OString(&cStrDelim
, 1, eCharSet
);
73 rtl_TextEncodingInfo aInfo
;
74 aInfo
.StructSize
= sizeof(aInfo
);
75 if ( rtl_getTextEncodingInfo( eCharSet
, &aInfo
) )
77 bContextOrNotAsciiEncoding
=
78 (((aInfo
.Flags
& RTL_TEXTENCODING_INFO_CONTEXT
) != 0) ||
79 ((aInfo
.Flags
& RTL_TEXTENCODING_INFO_ASCII
) == 0));
80 if ( bContextOrNotAsciiEncoding
)
81 aStrDelimDecoded
= OStringToOUString(aStrDelimEncoded
, eCharSet
);
84 bContextOrNotAsciiEncoding
= false;
87 const char p2DoubleQuotes_LF
[] = "\"\"\n";
88 const char pSpecDataType_LF
[] = "-1,0\n";
89 const char pEmptyData
[] = "1,0\n\"\"\n";
90 const char pStringData
[] = "1,0\n";
91 const char pNumData
[] = "0,";
92 const char pNumDataERROR
[] = "0,0\nERROR\n";
96 SCCOL nEndCol
= rRange
.aEnd
.Col();
97 SCROW nEndRow
= rRange
.aEnd
.Row();
98 SCCOL nNumCols
= nEndCol
- rRange
.aStart
.Col() + 1;
99 SCROW nNumRows
= nEndRow
- rRange
.aStart
.Row() + 1;
100 SCTAB nTab
= rRange
.aStart
.Tab();
102 ScProgress
aPrgrsBar( pDoc
->GetDocumentShell(), ScResId( STR_LOAD_DOC
), nNumRows
, true );
104 aPrgrsBar
.SetState( 0 );
107 OSL_ENSURE( pDoc
->HasTable( nTab
), "*ScExportDif(): Table not existent!" );
109 pDoc
->GetName( nTab
, aString
);
110 aOS
.append(OUString::Concat(pKeyTABLE
)
114 rOut
.WriteUnicodeOrByteText(aOS
);
118 aOS
.append(OUString::Concat(pKeyVECTORS
)
120 + OUString::number(static_cast<sal_Int32
>(nNumCols
))
122 + p2DoubleQuotes_LF
);
123 rOut
.WriteUnicodeOrByteText(aOS
);
127 aOS
.append(OUString::Concat(pKeyTUPLES
)
129 + OUString::number(static_cast<sal_Int32
>(nNumRows
))
131 + p2DoubleQuotes_LF
);
132 rOut
.WriteUnicodeOrByteText(aOS
);
136 aOS
.append(OUString::Concat(pKeyDATA
)
138 + p2DoubleQuotes_LF
);
139 rOut
.WriteUnicodeOrByteText(aOS
);
145 for( nRowCnt
= rRange
.aStart
.Row() ; nRowCnt
<= nEndRow
; nRowCnt
++ )
147 assert( aOS
.isEmpty() && "aOS should be empty");
148 aOS
.append(OUString::Concat(pSpecDataType_LF
)
151 rOut
.WriteUnicodeOrByteText(aOS
);
153 for( nColCnt
= rRange
.aStart
.Col() ; nColCnt
<= nEndCol
; nColCnt
++ )
155 assert( aOS
.isEmpty() && "aOS should be empty");
156 bool bWriteStringData
= false;
157 ScRefCellValue
aCell(*pDoc
, ScAddress(nColCnt
, nRowCnt
, nTab
));
159 switch (aCell
.getType())
162 aOS
.append(pEmptyData
);
165 aString
= pDoc
->GetInputString( nColCnt
, nRowCnt
, nTab
);
166 aOS
.append(pNumData
+ aString
+ "\nV\n");
169 case CELLTYPE_STRING
:
170 aString
= aCell
.getString(pDoc
);
171 bWriteStringData
= true;
173 case CELLTYPE_FORMULA
:
174 if (aCell
.getFormula()->GetErrCode() != FormulaError::NONE
)
175 aOS
.append(pNumDataERROR
);
176 else if (aCell
.getFormula()->IsValue())
178 aString
= pDoc
->GetInputString( nColCnt
, nRowCnt
, nTab
);
179 aOS
.append(pNumData
+ aString
+ "\nV\n");
183 aString
= aCell
.getFormula()->GetString().getString();
184 bWriteStringData
= true;
191 if ( !bWriteStringData
)
193 rOut
.WriteUnicodeOrByteText(aOS
);
198 // for an explanation why this complicated, see
199 // sc/source/ui/docshell/docsh.cxx:ScDocShell::AsciiSave()
200 // In fact we should create a common method if this would be
201 // needed just one more time...
202 assert( aOS
.isEmpty() && "aOS should be empty");
203 OUString aTmpStr
= aString
;
204 aOS
.append(pStringData
);
205 rOut
.WriteUnicodeOrByteText(aOS
, eCharSet
);
207 if ( eCharSet
== RTL_TEXTENCODING_UNICODE
)
209 // the goal is to replace cStrDelim by cStrDelim+cStrDelim
210 OUString
strFrom(cStrDelim
);
211 OUString strTo
= strFrom
+ strFrom
;
212 aTmpStr
= aTmpStr
.replaceAll(strFrom
, strTo
);
213 rOut
.WriteUniOrByteChar( cStrDelim
, eCharSet
);
214 rOut
.WriteUnicodeOrByteText(aTmpStr
, eCharSet
);
215 rOut
.WriteUniOrByteChar( cStrDelim
, eCharSet
);
217 else if ( bContextOrNotAsciiEncoding
)
220 OString aStrEnc
= OUStringToOString(aTmpStr
, eCharSet
);
222 OUString aStrDec
= OStringToOUString(aStrEnc
, eCharSet
);
223 // search on re-decoded string
224 OUString aStrTo
= aStrDelimDecoded
+ aStrDelimDecoded
;
225 aStrDec
= aStrDec
.replaceAll(aStrDelimDecoded
, aStrTo
);
226 // write byte re-encoded
227 rOut
.WriteUniOrByteChar( cStrDelim
, eCharSet
);
228 rOut
.WriteUnicodeOrByteText( aStrDec
, eCharSet
);
229 rOut
.WriteUniOrByteChar( cStrDelim
, eCharSet
);
233 OString aStrEnc
= OUStringToOString(aTmpStr
, eCharSet
);
234 // search on encoded string
235 OString aStrTo
= aStrDelimEncoded
+ aStrDelimEncoded
;
236 aStrEnc
= aStrEnc
.replaceAll(aStrDelimEncoded
, aStrTo
);
237 // write byte encoded
238 rOut
.WriteBytes(aStrDelimEncoded
.getStr(), aStrDelimEncoded
.getLength());
239 rOut
.WriteBytes(aStrEnc
.getStr(), aStrEnc
.getLength());
240 rOut
.WriteBytes(aStrDelimEncoded
.getStr(), aStrDelimEncoded
.getLength());
242 rOut
.WriteUniOrByteChar( '\n', eCharSet
);
245 aPrgrsBar
.SetState( nRowCnt
);
248 assert( aOS
.isEmpty() && "aOS should be empty");
249 aOS
.append(OUString::Concat(pSpecDataType_LF
)
252 rOut
.WriteUnicodeOrByteText(aOS
);
255 // restore original value
256 rOut
.SetStreamCharSet( eStreamCharSet
);
259 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */