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 "XMLExportDDELinks.hxx"
31 #include <xmloff/xmltoken.hxx>
32 #include <xmloff/xmlnmspe.hxx>
33 #include <xmloff/nmspmap.hxx>
34 #include <xmloff/xmluconv.hxx>
35 #include "xmlexprt.hxx"
36 #include "unonames.hxx"
37 #include "document.hxx"
38 #include "scmatrix.hxx"
39 #include <com/sun/star/sheet/XDDELink.hpp>
40 
41 class ScMatrix;
42 
43 using namespace com::sun::star;
44 using namespace xmloff::token;
45 
ScXMLExportDDELinks(ScXMLExport & rTempExport)46 ScXMLExportDDELinks::ScXMLExportDDELinks(ScXMLExport& rTempExport)
47 	: rExport(rTempExport)
48 {
49 }
50 
~ScXMLExportDDELinks()51 ScXMLExportDDELinks::~ScXMLExportDDELinks()
52 {
53 }
54 
CellsEqual(const sal_Bool bPrevEmpty,const sal_Bool bPrevString,const String & sPrevValue,const double & fPrevValue,const sal_Bool bEmpty,const sal_Bool bString,const String & sValue,const double & fValue)55 sal_Bool ScXMLExportDDELinks::CellsEqual(const sal_Bool bPrevEmpty, const sal_Bool bPrevString, const String& sPrevValue, const double& fPrevValue,
56 		 			const sal_Bool bEmpty, const sal_Bool bString, const String& sValue, const double& fValue)
57 {
58 	if (bEmpty == bPrevEmpty)
59 		if (bEmpty)
60 			return sal_True;
61 		else if (bString == bPrevString)
62 			if (bString)
63 				return (sPrevValue == sValue);
64 			else
65 				return (fPrevValue == fValue);
66 		else
67 			return sal_False;
68 	else
69 		return sal_False;
70 }
71 
WriteCell(const sal_Bool bEmpty,const sal_Bool bString,const String & sValue,const double & fValue,const sal_Int32 nRepeat)72 void ScXMLExportDDELinks::WriteCell(const sal_Bool bEmpty, const sal_Bool bString, const String& sValue, const double& fValue, const sal_Int32 nRepeat)
73 {
74 	rtl::OUStringBuffer sBuffer;
75 	if (!bEmpty)
76 	{
77 		if (bString)
78 		{
79 			rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_STRING);
80 			rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_STRING_VALUE, rtl::OUString(sValue));
81 		}
82 		else
83 		{
84 			rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_FLOAT);
85 			rExport.GetMM100UnitConverter().convertDouble(sBuffer, fValue);
86 			rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_VALUE, sBuffer.makeStringAndClear());
87 		}
88 	}
89 	if (nRepeat > 1)
90 	{
91 		rExport.GetMM100UnitConverter().convertNumber(sBuffer, nRepeat);
92 		rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, sBuffer.makeStringAndClear());
93 	}
94 	SvXMLElementExport(rExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, sal_True, sal_True);
95 }
96 
WriteTable(const sal_Int32 nPos)97 void ScXMLExportDDELinks::WriteTable(const sal_Int32 nPos)
98 {
99     const ScMatrix* pMatrix(NULL);
100     if (rExport.GetDocument())
101         pMatrix = rExport.GetDocument()->GetDdeLinkResultMatrix( static_cast<sal_uInt16>(nPos) );
102     if (pMatrix)
103 	{
104         SCSIZE nuCol;
105         SCSIZE nuRow;
106         pMatrix->GetDimensions( nuCol, nuRow );
107         sal_Int32 nRowCount = static_cast<sal_Int32>(nuRow);
108         sal_Int32 nColCount = static_cast<sal_Int32>(nuCol);
109 		SvXMLElementExport aTableElem(rExport, XML_NAMESPACE_TABLE, XML_TABLE, sal_True, sal_True);
110 		rtl::OUStringBuffer sBuffer;
111 		if (nColCount > 1)
112 		{
113 			rExport.GetMM100UnitConverter().convertNumber(sBuffer, nColCount);
114 			rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, sBuffer.makeStringAndClear());
115 		}
116 		{
117 			SvXMLElementExport aElemCol(rExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, sal_True, sal_True);
118 		}
119 		sal_Bool bPrevString(sal_True);
120 		sal_Bool bPrevEmpty(sal_True);
121 		double fPrevValue;
122 		String sPrevValue;
123 		sal_Int32 nRepeatColsCount(1);
124 		for(sal_Int32 nRow = 0; nRow < nRowCount; ++nRow)
125 		{
126 			SvXMLElementExport aElemRow(rExport, XML_NAMESPACE_TABLE, XML_TABLE_ROW, sal_True, sal_True);
127 			for(sal_Int32 nColumn = 0; nColumn < nColCount; ++nColumn)
128 			{
129                 ScMatValType nType = SC_MATVAL_VALUE;
130                 const ScMatrixValue* pMatVal = pMatrix->Get( static_cast<SCSIZE>(nColumn), static_cast<SCSIZE>(nRow), nType );
131                 sal_Bool bIsString = ScMatrix::IsNonValueType( nType);
132 
133 				if (nColumn == 0)
134                 {
135                     bPrevEmpty = !pMatVal;
136                     bPrevString = bIsString;
137                     if( bIsString )
138                         sPrevValue = pMatVal->GetString();
139                     else
140                         fPrevValue = pMatVal->fVal;
141                 }
142 				else
143 				{
144 					double fValue;
145 					String sValue;
146                     sal_Bool bEmpty(!pMatVal);
147                     sal_Bool bString(bIsString);
148                     if( bIsString )
149                         sValue = pMatVal->GetString();
150                     else
151                         fValue = pMatVal->fVal;
152 
153 					if (CellsEqual(bPrevEmpty, bPrevString, sPrevValue, fPrevValue,
154 								bEmpty, bString, sValue, fValue))
155 						++nRepeatColsCount;
156 					else
157 					{
158 						WriteCell(bPrevEmpty, bPrevString, sPrevValue, fPrevValue, nRepeatColsCount);
159 						nRepeatColsCount = 1;
160 						bPrevEmpty = bEmpty;
161 						fPrevValue = fValue;
162 						sPrevValue = sValue;
163 					}
164 				}
165 			}
166 			WriteCell(bPrevEmpty, bPrevString, sPrevValue, fPrevValue, nRepeatColsCount);
167 			nRepeatColsCount = 1;
168 		}
169 	}
170 }
171 
WriteDDELinks(uno::Reference<sheet::XSpreadsheetDocument> & xSpreadDoc)172 void ScXMLExportDDELinks::WriteDDELinks(uno::Reference<sheet::XSpreadsheetDocument>& xSpreadDoc)
173 {
174 	uno::Reference <beans::XPropertySet> xPropertySet (xSpreadDoc, uno::UNO_QUERY);
175 	if (xPropertySet.is())
176 	{
177         uno::Reference<container::XIndexAccess> xIndex(xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_DDELINKS))), uno::UNO_QUERY);
178 		if (xIndex.is())
179 		{
180 			sal_Int32 nCount = xIndex->getCount();
181 			if (nCount)
182 			{
183 				SvXMLElementExport aElemDDEs(rExport, XML_NAMESPACE_TABLE, XML_DDE_LINKS, sal_True, sal_True);
184 				for (sal_uInt16 nDDELink = 0; nDDELink < nCount; ++nDDELink)
185 				{
186                     uno::Reference<sheet::XDDELink> xDDELink(xIndex->getByIndex(nDDELink), uno::UNO_QUERY);
187 					if (xDDELink.is())
188 					{
189 						SvXMLElementExport aElemDDE(rExport, XML_NAMESPACE_TABLE, XML_DDE_LINK, sal_True, sal_True);
190 						{
191 							rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_APPLICATION, xDDELink->getApplication());
192 							rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_TOPIC, xDDELink->getTopic());
193 							rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_ITEM, xDDELink->getItem());
194 							rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_AUTOMATIC_UPDATE, XML_TRUE);
195                             sal_uInt8 nMode;
196 							if (rExport.GetDocument() &&
197 								rExport.GetDocument()->GetDdeLinkMode(nDDELink, nMode))
198 							{
199 								switch (nMode)
200 								{
201 									case SC_DDE_ENGLISH :
202 										rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONVERSION_MODE, XML_INTO_ENGLISH_NUMBER);
203 									break;
204 									case SC_DDE_TEXT :
205 										rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONVERSION_MODE, XML_KEEP_TEXT);
206 									break;
207 								}
208 							}
209 							SvXMLElementExport(rExport, XML_NAMESPACE_OFFICE, XML_DDE_SOURCE, sal_True, sal_True);
210 						}
211 						WriteTable(nDDELink);
212 					}
213 				}
214 			}
215 		}
216 	}
217 }
218