LibreOffice Module sc (master)  1
difexp.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <dif.hxx>
21 #include <document.hxx>
22 #include <formulacell.hxx>
23 #include <globstr.hrc>
24 #include <scresid.hxx>
25 #include <global.hxx>
26 #include <progress.hxx>
27 #include <rtl/tencinfo.h>
28 #include <ftools.hxx>
29 #include <cellvalue.hxx>
30 #include <rtl/strbuf.hxx>
31 #include <osl/diagnose.h>
32 #include <formula/errorcodes.hxx>
33 #include <tools/stream.hxx>
34 
36  const ScAddress& rOutPos, const rtl_TextEncoding eNach )
37 {
38  SCCOL nEndCol;
39  SCROW nEndRow;
40  pDoc->GetTableArea( rOutPos.Tab(), nEndCol, nEndRow );
41  ScAddress aEnd( nEndCol, nEndRow, rOutPos.Tab() );
42  ScAddress aStart( rOutPos );
43 
44  aStart.PutInOrder( aEnd );
45 
46  ScExportDif( rStream, pDoc, ScRange( aStart, aEnd ), eNach );
47 }
48 
50  const ScRange&rRange, const rtl_TextEncoding eCharSet )
51 {
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!" );
55 
56  const rtl_TextEncoding eStreamCharSet = rOut.GetStreamCharSet();
57  if ( eStreamCharSet != eCharSet )
58  rOut.SetStreamCharSet( eCharSet );
59 
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 )
65  {
67  bContextOrNotAsciiEncoding = false;
68  }
69  else
70  {
71  aStrDelimEncoded = OString(&cStrDelim, 1, eCharSet);
72  rtl_TextEncodingInfo aInfo;
73  aInfo.StructSize = sizeof(aInfo);
74  if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) )
75  {
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);
81  }
82  else
83  bContextOrNotAsciiEncoding = false;
84  }
85 
86  const char p2DoubleQuotes_LF[] = "\"\"\n";
87  const char pSpecDataType_LF[] = "-1,0\n";
88  const char pEmptyData[] = "1,0\n\"\"\n";
89  const char pStringData[] = "1,0\n";
90  const char pNumData[] = "0,";
91  const char pNumDataERROR[] = "0,0\nERROR\n";
92 
93  OUStringBuffer aOS;
94  OUString aString;
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();
100 
101  ScProgress aPrgrsBar( pDoc->GetDocumentShell(), ScResId( STR_LOAD_DOC ), nNumRows, true );
102 
103  aPrgrsBar.SetState( 0 );
104 
105  // TABLE
106  OSL_ENSURE( pDoc->HasTable( nTab ), "*ScExportDif(): Table not existent!" );
107 
108  aOS.append(pKeyTABLE);
109  aOS.append("\n0,1\n\"");
110 
111  pDoc->GetName( nTab, aString );
112  aOS.append(aString);
113  aOS.append("\"\n");
114  rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
115 
116  // VECTORS
117  aOS.append(pKeyVECTORS);
118  aOS.append("\n0,");
119  aOS.append(static_cast<sal_Int32>(nNumCols));
120  aOS.append('\n');
121  aOS.append(p2DoubleQuotes_LF);
122  rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
123 
124  // TUPLES
125  aOS.append(pKeyTUPLES);
126  aOS.append("\n0,");
127  aOS.append(static_cast<sal_Int32>(nNumRows));
128  aOS.append('\n');
129  aOS.append(p2DoubleQuotes_LF);
130  rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
131 
132  // DATA
133  aOS.append(pKeyDATA);
134  aOS.append("\n0,0\n");
135  aOS.append(p2DoubleQuotes_LF);
136  rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
137 
138  SCCOL nColCnt;
139  SCROW nRowCnt;
140 
141  for( nRowCnt = rRange.aStart.Row() ; nRowCnt <= nEndRow ; nRowCnt++ )
142  {
143  assert( aOS.isEmpty() && "aOS should be empty");
144  aOS.append(pSpecDataType_LF);
145  aOS.append(pKeyBOT);
146  aOS.append('\n');
147  rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
148  for( nColCnt = rRange.aStart.Col() ; nColCnt <= nEndCol ; nColCnt++ )
149  {
150  assert( aOS.isEmpty() && "aOS should be empty");
151  bool bWriteStringData = false;
152  ScRefCellValue aCell(*pDoc, ScAddress(nColCnt, nRowCnt, nTab));
153 
154  switch (aCell.meType)
155  {
156  case CELLTYPE_NONE:
157  aOS.append(pEmptyData);
158  break;
159  case CELLTYPE_VALUE:
160  aOS.append(pNumData);
161  pDoc->GetInputString( nColCnt, nRowCnt, nTab, aString );
162  aOS.append(aString);
163  aOS.append("\nV\n");
164  break;
165  case CELLTYPE_EDIT:
166  case CELLTYPE_STRING:
167  aString = aCell.getString(pDoc);
168  bWriteStringData = true;
169  break;
170  case CELLTYPE_FORMULA:
171  if (aCell.mpFormula->GetErrCode() != FormulaError::NONE)
172  aOS.append(pNumDataERROR);
173  else if (aCell.mpFormula->IsValue())
174  {
175  aOS.append(pNumData);
176  pDoc->GetInputString( nColCnt, nRowCnt, nTab, aString );
177  aOS.append(aString);
178  aOS.append("\nV\n");
179  }
180  else
181  {
182  aString = aCell.mpFormula->GetString().getString();
183  bWriteStringData = true;
184  }
185 
186  break;
187  default:;
188  }
189 
190  if ( !bWriteStringData )
191  rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
192  else
193  {
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 )
203  {
204  sal_Int32 nPos = aTmpStr.indexOf( cStrDelim );
205  while ( nPos != -1 )
206  {
207  aTmpStr = aTmpStr.replaceAt( nPos, 0, OUString(cStrDelim) );
208  nPos = aTmpStr.indexOf( cStrDelim, nPos+2 );
209  }
210  rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
211  write_uInt16s_FromOUString(rOut, aTmpStr);
212  rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
213  }
214  else if ( bContextOrNotAsciiEncoding )
215  {
216  // to byte encoding
217  OString aStrEnc = OUStringToOString(aTmpStr, eCharSet);
218  // back to Unicode
219  OUString aStrDec = OStringToOUString(aStrEnc, eCharSet);
220  // search on re-decoded string
221  sal_Int32 nPos = aStrDec.indexOf(aStrDelimDecoded);
222  while (nPos >= 0)
223  {
224  OUStringBuffer aBuf(aStrDec);
225  aBuf.insert(nPos, aStrDelimDecoded);
226  aStrDec = aBuf.makeStringAndClear();
227  nPos = aStrDec.indexOf(
228  aStrDelimDecoded, nPos+1+aStrDelimDecoded.getLength());
229  }
230  // write byte re-encoded
231  rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
232  rOut.WriteUnicodeOrByteText( aStrDec, eCharSet );
233  rOut.WriteUniOrByteChar( cStrDelim, eCharSet );
234  }
235  else
236  {
237  OString aStrEnc = OUStringToOString(aTmpStr, eCharSet);
238  // search on encoded string
239  sal_Int32 nPos = aStrEnc.indexOf(aStrDelimEncoded);
240  while (nPos >= 0)
241  {
242  OStringBuffer aBuf(aStrEnc);
243  aBuf.insert(nPos, aStrDelimEncoded);
244  aStrEnc = aBuf.makeStringAndClear();
245  nPos = aStrEnc.indexOf(
246  aStrDelimEncoded, nPos+1+aStrDelimEncoded.getLength());
247  }
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());
252  }
253  rOut.WriteUniOrByteChar( '\n', eCharSet );
254  }
255  }
256  aPrgrsBar.SetState( nRowCnt );
257  }
258 
259  assert( aOS.isEmpty() && "aOS should be empty");
260  aOS.append(pSpecDataType_LF);
261  aOS.append(pKeyEOD);
262  aOS.append('\n');
263  rOut.WriteUnicodeOrByteText(aOS.makeStringAndClear());
264 
265  // restore original value
266  rOut.SetStreamCharSet( eStreamCharSet );
267 }
268 
269 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::size_t write_uInt16s_FromOUString(SvStream &rStrm, const OUString &rStr, std::size_t nUnits)
OUString getString() const
ScAddress aStart
Definition: address.hxx:500
SC_DLLPUBLIC void GetInputString(SCCOL nCol, SCROW nRow, SCTAB nTab, OUString &rString)
Definition: document.cxx:3542
const sal_Unicode pKeyTABLE[]
Definition: difimp.cxx:35
SCROW Row() const
Definition: address.hxx:262
OUString getString(const ScDocument *pDoc) const
Retrieve string value.
Definition: cellvalue.cxx:660
const sal_Unicode pKeyBOT[]
Definition: difimp.cxx:39
const sal_Unicode pKeyVECTORS[]
Definition: difimp.cxx:36
virtual void ScExportDif(SvStream &, ScDocument *, const ScAddress &rOutPos, const rtl_TextEncoding eDest) override
Definition: difexp.cxx:35
aBuf
ScAddress aEnd
Definition: address.hxx:501
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:104
sal_uInt16 sal_Unicode
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
FormulaError GetErrCode()
SC_DLLPUBLIC bool HasTable(SCTAB nTab) const
Definition: document.cxx:190
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:111
SCTAB Tab() const
Definition: address.hxx:271
const sal_Unicode pKeyTUPLES[]
Definition: difimp.cxx:37
sal_Int16 SCCOL
Definition: types.hxx:22
std::size_t WriteBytes(const void *pData, std::size_t nSize)
OUString ScResId(const char *pId)
Definition: scdll.cxx:95
void StartWritingUnicodeText()
const sal_Unicode pKeyDATA[]
Definition: difimp.cxx:38
SCCOL Col() const
Definition: address.hxx:267
OString OUStringToOString(const OUString &str, ConnectionSettings const *settings)
CellType meType
Definition: cellvalue.hxx:106
svl::SharedString GetString()
void SetState(sal_uLong nVal, sal_uLong nNewRange=0)
Definition: progress.hxx:79
sal_Int32 SCROW
Definition: types.hxx:18
const sal_Unicode pKeyEOD[]
Definition: difimp.cxx:40
SC_DLLPUBLIC bool GetTableArea(SCTAB nTab, SCCOL &rEndCol, SCROW &rEndRow) const
Definition: document.cxx:1028
void SetStreamCharSet(rtl_TextEncoding eCharSet)
rtl_TextEncoding GetStreamCharSet() const
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1061
bool WriteUnicodeOrByteText(const OUString &rStr, rtl_TextEncoding eDestCharSet)
bool WriteUniOrByteChar(sal_Unicode ch, rtl_TextEncoding eDestCharSet)
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:212
sal_uInt16 nPos
sal_Int16 SCTAB
Definition: types.hxx:23