1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 #include "XMLDDELinksContext.hxx"
31 #include "xmlimprt.hxx"
32 #include "document.hxx"
33 #include "scmatrix.hxx"
34 #include <xmloff/xmltoken.hxx>
35 #include <xmloff/xmlnmspe.hxx>
36 #include <xmloff/nmspmap.hxx>
37 #include <xmloff/xmluconv.hxx>
38 #include <tools/debug.hxx>
39 
40 using namespace com::sun::star;
41 using namespace xmloff::token;
42 using ::rtl::OUString;
43 
44 //------------------------------------------------------------------
45 
ScXMLDDELinksContext(ScXMLImport & rImport,sal_uInt16 nPrfx,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> &)46 ScXMLDDELinksContext::ScXMLDDELinksContext( ScXMLImport& rImport,
47 									  sal_uInt16 nPrfx,
48 									  const ::rtl::OUString& rLName,
49 									  const ::com::sun::star::uno::Reference<
50                                       ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ ) :
51 	SvXMLImportContext( rImport, nPrfx, rLName )
52 {
53 	// here are no attributes
54 	rImport.LockSolarMutex();
55 }
56 
~ScXMLDDELinksContext()57 ScXMLDDELinksContext::~ScXMLDDELinksContext()
58 {
59 	GetScImport().UnlockSolarMutex();
60 }
61 
CreateChildContext(sal_uInt16 nPrefix,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList)62 SvXMLImportContext *ScXMLDDELinksContext::CreateChildContext( sal_uInt16 nPrefix,
63 											const ::rtl::OUString& rLName,
64 											const ::com::sun::star::uno::Reference<
65 									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList )
66 {
67 	SvXMLImportContext *pContext = 0;
68 
69 	if ((nPrefix == XML_NAMESPACE_TABLE) && IsXMLToken(rLName, XML_DDE_LINK))
70 		pContext = new ScXMLDDELinkContext(GetScImport(), nPrefix, rLName, xAttrList);
71 
72 	if( !pContext )
73 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
74 
75 	return pContext;
76 }
77 
EndElement()78 void ScXMLDDELinksContext::EndElement()
79 {
80 }
81 
ScXMLDDELinkContext(ScXMLImport & rImport,sal_uInt16 nPrfx,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> &)82 ScXMLDDELinkContext::ScXMLDDELinkContext( ScXMLImport& rImport,
83 									  sal_uInt16 nPrfx,
84 									  const ::rtl::OUString& rLName,
85 									  const ::com::sun::star::uno::Reference<
86                                       ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ ) :
87 	SvXMLImportContext( rImport, nPrfx, rLName ),
88 	aDDELinkTable(),
89 	aDDELinkRow(),
90 	sApplication(),
91 	sTopic(),
92 	sItem(),
93 	nPosition(-1),
94 	nColumns(0),
95 	nRows(0),
96 	nMode(SC_DDE_DEFAULT)
97 {
98 	// here are no attributes
99 }
100 
~ScXMLDDELinkContext()101 ScXMLDDELinkContext::~ScXMLDDELinkContext()
102 {
103 }
104 
CreateChildContext(sal_uInt16 nPrefix,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList)105 SvXMLImportContext *ScXMLDDELinkContext::CreateChildContext( sal_uInt16 nPrefix,
106 											const ::rtl::OUString& rLName,
107 											const ::com::sun::star::uno::Reference<
108 									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList )
109 {
110 	SvXMLImportContext *pContext = 0;
111 
112 	if ((nPrefix == XML_NAMESPACE_OFFICE) && IsXMLToken(rLName, XML_DDE_SOURCE))
113 		pContext = new ScXMLDDESourceContext(GetScImport(), nPrefix, rLName, xAttrList, this);
114 	else if ((nPrefix == XML_NAMESPACE_TABLE) && IsXMLToken(rLName, XML_TABLE))
115 		pContext = new ScXMLDDETableContext(GetScImport(), nPrefix, rLName, xAttrList, this);
116 
117 	if( !pContext )
118 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
119 
120 	return pContext;
121 }
122 
CreateDDELink()123 void ScXMLDDELinkContext::CreateDDELink()
124 {
125 	if (GetScImport().GetDocument() &&
126 		sApplication.getLength() &&
127 		sTopic.getLength() &&
128 		sItem.getLength())
129 	{
130 		String sAppl(sApplication);
131 		String sTop(sTopic);
132 		String sIt(sItem);
133 		GetScImport().GetDocument()->CreateDdeLink(sAppl, sTop, sIt, nMode);
134 		sal_uInt16 nPos;
135 		if(GetScImport().GetDocument()->FindDdeLink(sAppl, sTop, sIt, nMode, nPos))
136 			nPosition = nPos;
137 		else
138 			nPosition = -1;
139 		DBG_ASSERT(nPosition > -1, "DDE Link not inserted");
140 	}
141 }
142 
AddCellToRow(const ScDDELinkCell & aCell)143 void ScXMLDDELinkContext::AddCellToRow(const ScDDELinkCell& aCell)
144 {
145 	aDDELinkRow.push_back(aCell);
146 }
147 
AddRowsToTable(const sal_Int32 nRowsP)148 void ScXMLDDELinkContext::AddRowsToTable(const sal_Int32 nRowsP)
149 {
150 	for (sal_Int32 i = 0; i < nRowsP; ++i)
151 		aDDELinkTable.insert(aDDELinkTable.end(), aDDELinkRow.begin(), aDDELinkRow.end());
152 	aDDELinkRow.clear();
153 }
154 
EndElement()155 void ScXMLDDELinkContext::EndElement()
156 {
157     if (nPosition > -1 && nColumns && nRows && GetScImport().GetDocument())
158 	{
159         bool bSizeMatch = (static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size());
160         DBG_ASSERT( bSizeMatch, "ScXMLDDELinkContext::EndElement: matrix dimension doesn't match cells count");
161         // Excel writes bad ODF in that it does not write the
162         // table:number-columns-repeated attribute of the
163         // <table:table-column> element, but apparently uses the number of
164         // <table:table-cell> elements within a <table:table-row> element to
165         // determine the column count instead. Be lenient ...
166         if (!bSizeMatch && nColumns == 1)
167         {
168             nColumns = aDDELinkTable.size() / nRows;
169             DBG_ASSERT( static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size(),
170                     "ScXMLDDELinkContext::EndElement: adapted matrix dimension doesn't match either");
171         }
172         ScMatrixRef pMatrix = new ScMatrix( static_cast<SCSIZE>(nColumns), static_cast<SCSIZE>(nRows) );
173         sal_Int32 nCol(0);
174         sal_Int32 nRow(-1);
175         sal_Int32 nIndex(0);
176         ScDDELinkCells::iterator aItr(aDDELinkTable.begin());
177         ScDDELinkCells::iterator aEndItr(aDDELinkTable.end());
178         while (aItr != aEndItr)
179         {
180             if (nIndex % nColumns == 0)
181             {
182                 ++nRow;
183                 nCol = 0;
184             }
185             else
186                 ++nCol;
187 
188             SCSIZE nScCol( static_cast< SCSIZE >( nCol ) );
189             SCSIZE nScRow( static_cast< SCSIZE >( nRow ) );
190             if( aItr->bEmpty )
191                 pMatrix->PutEmpty( nScCol, nScRow );
192             else if( aItr->bString )
193                 pMatrix->PutString( aItr->sValue, nScCol, nScRow );
194             else
195                 pMatrix->PutDouble( aItr->fValue, nScCol, nScRow );
196 
197             ++nIndex;
198             ++aItr;
199 		}
200 
201         GetScImport().GetDocument()->SetDdeLinkResultMatrix( static_cast< sal_uInt16 >( nPosition ), pMatrix );
202 	}
203 }
204 
ScXMLDDESourceContext(ScXMLImport & rImport,sal_uInt16 nPrfx,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList,ScXMLDDELinkContext * pTempDDELink)205 ScXMLDDESourceContext::ScXMLDDESourceContext( ScXMLImport& rImport,
206 									  sal_uInt16 nPrfx,
207 									  const ::rtl::OUString& rLName,
208 									  const ::com::sun::star::uno::Reference<
209 									  ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
210 										ScXMLDDELinkContext* pTempDDELink) :
211 	SvXMLImportContext( rImport, nPrfx, rLName ),
212 	pDDELink(pTempDDELink)
213 {
214 	if( !xAttrList.is() ) return;
215 
216 	sal_Int16				nAttrCount		= xAttrList->getLength();
217 
218 	for( sal_Int16 nIndex = 0; nIndex < nAttrCount; ++nIndex )
219 	{
220 		const rtl::OUString& sAttrName	(xAttrList->getNameByIndex( nIndex ));
221 		const rtl::OUString& sValue		(xAttrList->getValueByIndex( nIndex ));
222 		OUString aLocalName;
223 		sal_uInt16 nPrefix		= GetScImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
224 
225 		if (nPrefix == XML_NAMESPACE_OFFICE)
226 		{
227 			if (IsXMLToken(aLocalName, XML_DDE_APPLICATION))
228 				pDDELink->SetApplication(sValue);
229 			else if (IsXMLToken(aLocalName, XML_DDE_TOPIC))
230 				pDDELink->SetTopic(sValue);
231 			else if (IsXMLToken(aLocalName, XML_DDE_ITEM))
232 				pDDELink->SetItem(sValue);
233 		}
234 		else if ((nPrefix == XML_NAMESPACE_TABLE) && IsXMLToken(aLocalName, XML_CONVERSION_MODE))
235 		{
236 			if (IsXMLToken(sValue, XML_INTO_ENGLISH_NUMBER))
237 				pDDELink->SetMode(SC_DDE_ENGLISH);
238 			else if (IsXMLToken(sValue, XML_KEEP_TEXT))
239 				pDDELink->SetMode(SC_DDE_TEXT);
240 			else
241 				pDDELink->SetMode(SC_DDE_DEFAULT);
242 		}
243 	}
244 }
245 
~ScXMLDDESourceContext()246 ScXMLDDESourceContext::~ScXMLDDESourceContext()
247 {
248 }
249 
CreateChildContext(sal_uInt16 nPrefix,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> &)250 SvXMLImportContext *ScXMLDDESourceContext::CreateChildContext( sal_uInt16 nPrefix,
251 											const ::rtl::OUString& rLName,
252 											const ::com::sun::star::uno::Reference<
253                                         ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ )
254 {
255 	SvXMLImportContext *pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
256 
257 	return pContext;
258 }
259 
EndElement()260 void ScXMLDDESourceContext::EndElement()
261 {
262 	pDDELink->CreateDDELink();
263 }
264 
ScXMLDDETableContext(ScXMLImport & rImport,sal_uInt16 nPrfx,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> &,ScXMLDDELinkContext * pTempDDELink)265 ScXMLDDETableContext::ScXMLDDETableContext( ScXMLImport& rImport,
266 									  sal_uInt16 nPrfx,
267 									  const ::rtl::OUString& rLName,
268 									  const ::com::sun::star::uno::Reference<
269                                       ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */,
270 										ScXMLDDELinkContext* pTempDDELink) :
271 	SvXMLImportContext( rImport, nPrfx, rLName ),
272 	pDDELink(pTempDDELink)
273 {
274 	// here are no attributes
275 }
276 
~ScXMLDDETableContext()277 ScXMLDDETableContext::~ScXMLDDETableContext()
278 {
279 }
280 
CreateChildContext(sal_uInt16 nPrefix,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList)281 SvXMLImportContext *ScXMLDDETableContext::CreateChildContext( sal_uInt16 nPrefix,
282 											const ::rtl::OUString& rLName,
283 											const ::com::sun::star::uno::Reference<
284 									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList )
285 {
286 	SvXMLImportContext *pContext = NULL;
287 
288 	if (nPrefix == XML_NAMESPACE_TABLE)
289 	{
290 		if (IsXMLToken(rLName, XML_TABLE_COLUMN))
291 			pContext = new ScXMLDDEColumnContext(GetScImport(), nPrefix, rLName, xAttrList, pDDELink);
292 		else if (IsXMLToken(rLName, XML_TABLE_ROW))
293 			pContext = new ScXMLDDERowContext(GetScImport(), nPrefix, rLName, xAttrList, pDDELink);
294 	}
295 
296 	if (!pContext)
297 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
298 
299 	return pContext;
300 }
301 
EndElement()302 void ScXMLDDETableContext::EndElement()
303 {
304 }
305 
ScXMLDDEColumnContext(ScXMLImport & rImport,sal_uInt16 nPrfx,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList,ScXMLDDELinkContext * pTempDDELink)306 ScXMLDDEColumnContext::ScXMLDDEColumnContext( ScXMLImport& rImport,
307 									  sal_uInt16 nPrfx,
308 									  const ::rtl::OUString& rLName,
309 									  const ::com::sun::star::uno::Reference<
310 									  ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
311 										ScXMLDDELinkContext* pTempDDELink) :
312 	SvXMLImportContext( rImport, nPrfx, rLName ),
313 	pDDELink(pTempDDELink)
314 {
315 	if( !xAttrList.is() ) return;
316 	sal_Int32 nCols(1);
317 
318 	sal_Int16				nAttrCount		= xAttrList->getLength();
319 
320 	for( sal_Int16 nIndex = 0; nIndex < nAttrCount; ++nIndex )
321 	{
322 		const rtl::OUString& sAttrName	(xAttrList->getNameByIndex( nIndex ));
323 		const rtl::OUString& sValue		(xAttrList->getValueByIndex( nIndex ));
324 		OUString aLocalName;
325 		sal_uInt16 nPrefix		= GetScImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
326 
327 		if (nPrefix == XML_NAMESPACE_TABLE)
328 			if (IsXMLToken(aLocalName, XML_NUMBER_COLUMNS_REPEATED))
329 				GetScImport().GetMM100UnitConverter().convertNumber(nCols, sValue);
330 	}
331 	pDDELink->AddColumns(nCols);
332 }
333 
~ScXMLDDEColumnContext()334 ScXMLDDEColumnContext::~ScXMLDDEColumnContext()
335 {
336 }
337 
CreateChildContext(sal_uInt16 nPrefix,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> &)338 SvXMLImportContext *ScXMLDDEColumnContext::CreateChildContext( sal_uInt16 nPrefix,
339 											const ::rtl::OUString& rLName,
340 											const ::com::sun::star::uno::Reference<
341                                         ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ )
342 {
343 	SvXMLImportContext *pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
344 
345 	return pContext;
346 }
347 
EndElement()348 void ScXMLDDEColumnContext::EndElement()
349 {
350 }
351 
ScXMLDDERowContext(ScXMLImport & rImport,sal_uInt16 nPrfx,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList,ScXMLDDELinkContext * pTempDDELink)352 ScXMLDDERowContext::ScXMLDDERowContext( ScXMLImport& rImport,
353 									  sal_uInt16 nPrfx,
354 									  const ::rtl::OUString& rLName,
355 									  const ::com::sun::star::uno::Reference<
356 									  ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
357 										ScXMLDDELinkContext* pTempDDELink) :
358 	SvXMLImportContext( rImport, nPrfx, rLName ),
359 	pDDELink(pTempDDELink),
360 	nRows(1)
361 {
362 	if( !xAttrList.is() ) return;
363 
364 	sal_Int16				nAttrCount		= xAttrList->getLength();
365 
366 	for( sal_Int16 nIndex = 0; nIndex < nAttrCount; ++nIndex )
367 	{
368 		const rtl::OUString& sAttrName	(xAttrList->getNameByIndex( nIndex ));
369 		const rtl::OUString& sValue		(xAttrList->getValueByIndex( nIndex ));
370 		OUString aLocalName;
371 		sal_uInt16 nPrefix		= GetScImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
372 
373 		if (nPrefix == XML_NAMESPACE_TABLE)
374 			if (IsXMLToken(aLocalName, XML_NUMBER_ROWS_REPEATED))
375 				GetScImport().GetMM100UnitConverter().convertNumber(nRows, sValue);
376 	}
377 	pDDELink->AddRows(nRows);
378 }
379 
~ScXMLDDERowContext()380 ScXMLDDERowContext::~ScXMLDDERowContext()
381 {
382 }
383 
CreateChildContext(sal_uInt16 nPrefix,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList)384 SvXMLImportContext *ScXMLDDERowContext::CreateChildContext( sal_uInt16 nPrefix,
385 											const ::rtl::OUString& rLName,
386 											const ::com::sun::star::uno::Reference<
387 									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList )
388 {
389 	SvXMLImportContext *pContext = NULL;
390 
391 	if (nPrefix == XML_NAMESPACE_TABLE)
392 		if (IsXMLToken(rLName, XML_TABLE_CELL))
393 			pContext = new ScXMLDDECellContext(GetScImport(), nPrefix, rLName, xAttrList, pDDELink);
394 
395 	if (!pContext)
396 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
397 
398 	return pContext;
399 }
400 
EndElement()401 void ScXMLDDERowContext::EndElement()
402 {
403 	pDDELink->AddRowsToTable(nRows);
404 }
405 
ScXMLDDECellContext(ScXMLImport & rImport,sal_uInt16 nPrfx,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList,ScXMLDDELinkContext * pTempDDELink)406 ScXMLDDECellContext::ScXMLDDECellContext( ScXMLImport& rImport,
407 									  sal_uInt16 nPrfx,
408 									  const ::rtl::OUString& rLName,
409 									  const ::com::sun::star::uno::Reference<
410 									  ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
411 										ScXMLDDELinkContext* pTempDDELink) :
412 	SvXMLImportContext( rImport, nPrfx, rLName ),
413 	sValue(),
414 	fValue(),
415 	nCells(1),
416 	bString(sal_True),
417 	bString2(sal_True),
418 	bEmpty(sal_True),
419 	pDDELink(pTempDDELink)
420 {
421 	if( !xAttrList.is() ) return;
422 
423 	sal_Int16				nAttrCount		= xAttrList->getLength();
424 
425 	for( sal_Int16 nIndex = 0; nIndex < nAttrCount; ++nIndex )
426 	{
427 		const rtl::OUString& sAttrName	(xAttrList->getNameByIndex( nIndex ));
428 		const rtl::OUString& sTempValue	(xAttrList->getValueByIndex( nIndex ));
429 		OUString aLocalName;
430 		sal_uInt16 nPrefix		= GetScImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
431 
432 		if (nPrefix == XML_NAMESPACE_OFFICE)
433         {
434 			if (IsXMLToken(aLocalName, XML_VALUE_TYPE))
435 			{
436 				if (IsXMLToken(sTempValue, XML_STRING))
437 					bString = sal_True;
438 				else
439 					bString = sal_False;
440 			}
441 			else if (IsXMLToken(aLocalName, XML_STRING_VALUE))
442 			{
443 				sValue = sTempValue;
444 				bEmpty = sal_False;
445 				bString2 = sal_True;
446 			}
447 			else if (IsXMLToken(aLocalName, XML_VALUE))
448 			{
449 				GetScImport().GetMM100UnitConverter().convertDouble(fValue, sTempValue);
450 				bEmpty = sal_False;
451 				bString2 = sal_False;
452 			}
453         }
454 		else if (nPrefix == XML_NAMESPACE_TABLE)
455         {
456 			if (IsXMLToken(aLocalName, XML_NUMBER_COLUMNS_REPEATED))
457 				GetScImport().GetMM100UnitConverter().convertNumber(nCells, sTempValue);
458         }
459 	}
460 }
461 
~ScXMLDDECellContext()462 ScXMLDDECellContext::~ScXMLDDECellContext()
463 {
464 }
465 
CreateChildContext(sal_uInt16 nPrefix,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> &)466 SvXMLImportContext *ScXMLDDECellContext::CreateChildContext( sal_uInt16 nPrefix,
467 											const ::rtl::OUString& rLName,
468 											const ::com::sun::star::uno::Reference<
469                                         ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ )
470 {
471 	SvXMLImportContext *pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
472 
473 	return pContext;
474 }
475 
EndElement()476 void ScXMLDDECellContext::EndElement()
477 {
478 	DBG_ASSERT(bString == bString2, "something wrong with this type");
479 	ScDDELinkCell aCell;
480 	aCell.sValue = sValue;
481 	aCell.fValue = fValue;
482 	aCell.bEmpty = bEmpty;
483 	aCell.bString = bString2;
484 	for(sal_Int32 i = 0; i < nCells; ++i)
485 		pDDELink->AddCellToRow(aCell);
486 }
487