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_scfilt.hxx"
26
27
28
29 #include "colrowst.hxx"
30
31 #include <string.h>
32
33 #include "document.hxx"
34 #include "root.hxx"
35 #include "ftools.hxx"
36 #include "xltable.hxx"
37 #include "xistream.hxx"
38 #include "xistyle.hxx"
39 #include "queryparam.hxx"
40
41 // for filter manager
42 #include "excimp8.hxx"
43
44 // ============================================================================
45
46 const sal_uInt8 EXC_COLROW_USED = 0x01;
47 const sal_uInt8 EXC_COLROW_DEFAULT = 0x02;
48 const sal_uInt8 EXC_COLROW_HIDDEN = 0x04;
49 const sal_uInt8 EXC_COLROW_MAN = 0x08;
50
51 // ============================================================================
52
XclImpColRowSettings(const XclImpRoot & rRoot)53 XclImpColRowSettings::XclImpColRowSettings( const XclImpRoot& rRoot ) :
54 XclImpRoot( rRoot ),
55 mnMaxCol( rRoot.GetXclMaxPos().Col() ),
56 mnMaxRow( rRoot.GetXclMaxPos().Row() ),
57 mnLastScRow( -1 ),
58 mnDefWidth( STD_COL_WIDTH ),
59 mnDefHeight( static_cast< sal_uInt16 >( STD_ROW_HEIGHT ) ),
60 mnDefRowFlags( EXC_DEFROW_DEFAULTFLAGS ),
61 mbHasStdWidthRec( false ),
62 mbHasDefHeight( false ),
63 mbDirty( true )
64 {
65 maWidths.resize( static_cast< size_t >( mnMaxCol + 1 ), 0 );
66 maColFlags.resize( static_cast< size_t >( mnMaxCol + 1 ), 0 );
67 maHeights.resize( static_cast< size_t >( mnMaxRow + 1 ), 0 );
68 maRowFlags.resize( static_cast< size_t >( mnMaxRow + 1 ), 0 );
69 }
70
~XclImpColRowSettings()71 XclImpColRowSettings::~XclImpColRowSettings()
72 {
73 }
74
SetDefWidth(sal_uInt16 nDefWidth,bool bStdWidthRec)75 void XclImpColRowSettings::SetDefWidth( sal_uInt16 nDefWidth, bool bStdWidthRec )
76 {
77 if( bStdWidthRec )
78 {
79 // STANDARDWIDTH record overrides DEFCOLWIDTH record
80 mnDefWidth = nDefWidth;
81 mbHasStdWidthRec = true;
82 }
83 else if( !mbHasStdWidthRec )
84 {
85 // use DEFCOLWIDTH record only, if no STANDARDWIDTH record exists
86 mnDefWidth = nDefWidth;
87 }
88 }
89
SetWidthRange(SCCOL nScCol1,SCCOL nScCol2,sal_uInt16 nWidth)90 void XclImpColRowSettings::SetWidthRange( SCCOL nScCol1, SCCOL nScCol2, sal_uInt16 nWidth )
91 {
92 DBG_ASSERT( (0 <= nScCol1) && (nScCol1 <= nScCol2) && (nScCol2 <= mnMaxCol),
93 "XclImpColRowSettings::SetColWidthRange - invalid column range" );
94
95 nScCol2 = ::std::min( nScCol2, mnMaxCol );
96 if( (0 <= nScCol1) && (nScCol1 <= nScCol2) )
97 {
98 ::std::fill( maWidths.begin() + nScCol1, maWidths.begin() + nScCol2 + 1, nWidth );
99 for( ScfUInt8Vec::iterator aIt = maColFlags.begin() + nScCol1, aEnd = maColFlags.begin() + nScCol2 + 1; aIt != aEnd; ++aIt )
100 ::set_flag( *aIt, EXC_COLROW_USED );
101 }
102 }
103
HideCol(SCCOL nScCol)104 void XclImpColRowSettings::HideCol( SCCOL nScCol )
105 {
106 if( (0 <= nScCol) && (nScCol <= mnMaxCol) )
107 ::set_flag( maColFlags[ nScCol ], EXC_COLROW_HIDDEN );
108 }
109
HideColRange(SCCOL nScCol1,SCCOL nScCol2)110 void XclImpColRowSettings::HideColRange( SCCOL nScCol1, SCCOL nScCol2 )
111 {
112 DBG_ASSERT( (0 <= nScCol1) && (nScCol1 <= nScCol2) && (nScCol2 <= mnMaxCol), "XclImpColRowSettings::HideColRange - invalid column range" );
113 nScCol2 = ::std::min( nScCol2, mnMaxCol );
114 if( (0 <= nScCol1) && (nScCol1 <= nScCol2) )
115 for( ScfUInt8Vec::iterator aIt = maColFlags.begin() + nScCol1, aEnd = maColFlags.begin() + nScCol2 + 1; aIt != aEnd; ++aIt )
116 ::set_flag( *aIt, EXC_COLROW_HIDDEN );
117 }
118
SetDefHeight(sal_uInt16 nDefHeight,sal_uInt16 nFlags)119 void XclImpColRowSettings::SetDefHeight( sal_uInt16 nDefHeight, sal_uInt16 nFlags )
120 {
121 mnDefHeight = nDefHeight;
122 mnDefRowFlags = nFlags;
123 if( mnDefHeight == 0 )
124 {
125 mnDefHeight = static_cast< sal_uInt16 >( STD_ROW_HEIGHT );
126 ::set_flag( mnDefRowFlags, EXC_DEFROW_HIDDEN );
127 }
128 mbHasDefHeight = true;
129 }
130
SetHeight(SCROW nScRow,sal_uInt16 nHeight)131 void XclImpColRowSettings::SetHeight( SCROW nScRow, sal_uInt16 nHeight )
132 {
133 if( (0 <= nScRow) && (nScRow <= mnMaxRow) )
134 {
135 sal_uInt16 nRawHeight = nHeight & EXC_ROW_HEIGHTMASK;
136 bool bDefHeight = ::get_flag( nHeight, EXC_ROW_FLAGDEFHEIGHT ) || (nRawHeight == 0);
137 maHeights[ nScRow ] = nRawHeight;
138 sal_uInt8& rnFlags = maRowFlags[ nScRow ];
139 ::set_flag( rnFlags, EXC_COLROW_USED );
140 if( !bDefHeight && (nRawHeight == 0) )
141 ::set_flag( rnFlags, EXC_COLROW_HIDDEN );
142 ::set_flag( rnFlags, EXC_COLROW_DEFAULT, bDefHeight );
143 if( nScRow > mnLastScRow )
144 mnLastScRow = nScRow;
145 }
146 }
147
SetRowSettings(SCROW nScRow,sal_uInt16 nHeight,sal_uInt16 nFlags)148 void XclImpColRowSettings::SetRowSettings( SCROW nScRow, sal_uInt16 nHeight, sal_uInt16 nFlags )
149 {
150 if( (0 <= nScRow) && (nScRow <= mnMaxRow) )
151 {
152 SetHeight( nScRow, nHeight );
153 sal_uInt8& rnFlags = maRowFlags[ nScRow ];
154 if( ::get_flag( nFlags, EXC_ROW_UNSYNCED ) )
155 ::set_flag( rnFlags, EXC_COLROW_MAN );
156 if( ::get_flag( nFlags, EXC_ROW_HIDDEN ) )
157 ::set_flag( rnFlags, EXC_COLROW_HIDDEN );
158 }
159 }
160
SetManualRowHeight(SCROW nScRow)161 void XclImpColRowSettings::SetManualRowHeight( SCROW nScRow )
162 {
163 if( (0 <= nScRow) && (nScRow <= mnMaxRow) )
164 ::set_flag( maRowFlags[ nScRow ], EXC_COLROW_MAN );
165 }
166
SetDefaultXF(SCCOL nScCol1,SCCOL nScCol2,sal_uInt16 nXFIndex)167 void XclImpColRowSettings::SetDefaultXF( SCCOL nScCol1, SCCOL nScCol2, sal_uInt16 nXFIndex )
168 {
169 /* #109555# assign the default column formatting here to ensure that
170 explicit cell formatting is not overwritten. */
171 DBG_ASSERT( (0 <= nScCol1) && (nScCol1 <= nScCol2) && (nScCol2 <= mnMaxCol), "XclImpColRowSettings::SetDefaultXF - invalid column index" );
172 nScCol2 = ::std::min( nScCol2, mnMaxCol );
173 if( (0 <= nScCol1) && (nScCol1 <= nScCol2) )
174 {
175 XclImpXFRangeBuffer& rXFRangeBuffer = GetXFRangeBuffer();
176 for( SCCOL nScCol = nScCol1; nScCol <= nScCol2; ++nScCol )
177 rXFRangeBuffer.SetColumnDefXF( nScCol, nXFIndex );
178 }
179 }
180
Convert(SCTAB nScTab)181 void XclImpColRowSettings::Convert( SCTAB nScTab )
182 {
183 if( !mbDirty )
184 return;
185
186 ScDocument& rDoc = GetDoc();
187 rDoc.IncSizeRecalcLevel( nScTab );
188
189 // column widths ----------------------------------------------------------
190
191 for( SCCOL nScCol = 0; nScCol <= mnMaxCol; ++nScCol )
192 {
193 sal_uInt16 nWidth = ::get_flag( maColFlags[ nScCol ], EXC_COLROW_USED ) ? maWidths[ nScCol ] : mnDefWidth;
194 /* Hidden columns: remember hidden state, but do not set hidden state
195 in document here. Needed for #i11776#, no HIDDEN flags in the
196 document, until filters and outlines are inserted. */
197 if( nWidth == 0 )
198 {
199 ::set_flag( maColFlags[ nScCol ], EXC_COLROW_HIDDEN );
200 nWidth = mnDefWidth;
201 }
202 rDoc.SetColWidthOnly( nScCol, nScTab, nWidth );
203 }
204
205 // row heights ------------------------------------------------------------
206
207 // #i54252# set default row height
208 rDoc.SetRowHeightOnly( 0, MAXROW, nScTab, mnDefHeight );
209 if( ::get_flag( mnDefRowFlags, EXC_DEFROW_UNSYNCED ) )
210 // first access to row flags, do not ask for old flags
211 rDoc.SetRowFlags( 0, MAXROW, nScTab, CR_MANUALSIZE );
212 bool bDefHideRow = ::get_flag( mnDefRowFlags, EXC_DEFROW_HIDDEN );
213
214 SCROW nFirstScRow = -1;
215 sal_uInt16 nLastHeight = 0;
216 for( SCROW nScRow = 0; nScRow <= mnLastScRow ; ++nScRow )
217 {
218 // get height and hidden state from cached data
219 sal_uInt8 nFlags = maRowFlags[ nScRow ];
220 sal_uInt16 nHeight = 0;
221 bool bHideRow = false;
222 if( ::get_flag( nFlags, EXC_COLROW_USED ) )
223 {
224 if( ::get_flag( nFlags, EXC_COLROW_DEFAULT ) )
225 {
226 nHeight = mnDefHeight;
227 bHideRow = bDefHideRow;
228 }
229 else
230 {
231 nHeight = maHeights[ nScRow ];
232 if( nHeight == 0 )
233 {
234 nHeight = mnDefHeight;
235 bHideRow = true;
236 }
237 }
238
239 if( ::get_flag( nFlags, EXC_COLROW_MAN ) )
240 rDoc.SetRowFlags( nScRow, nScTab, rDoc.GetRowFlags( nScRow, nScTab ) | CR_MANUALSIZE );
241 }
242 else
243 {
244 nHeight = mnDefHeight;
245 bHideRow = bDefHideRow;
246 }
247
248 /* Hidden rows: remember hidden state, but do not set hidden state in
249 document here. Needed for #i11776#, no HIDDEN flags in the document,
250 until filters and outlines are inserted. */
251 if( bHideRow )
252 ::set_flag( maRowFlags[ nScRow ], EXC_COLROW_HIDDEN );
253
254 // set height range
255 if( (nLastHeight != nHeight) || (nScRow == 0) )
256 {
257 DBG_ASSERT( (nScRow == 0) || (nFirstScRow >= 0), "XclImpColRowSettings::Convert - algorithm error" );
258 if( nScRow > 0 )
259 rDoc.SetRowHeightOnly( nFirstScRow, nScRow - 1, nScTab, nLastHeight );
260
261 nFirstScRow = nScRow;
262 nLastHeight = nHeight;
263 }
264 }
265
266 // set row height of last portion
267 if( mnLastScRow >= 0 )
268 rDoc.SetRowHeightOnly( nFirstScRow, mnLastScRow, nScTab, nLastHeight );
269
270 // ------------------------------------------------------------------------
271
272 mbDirty = false;
273 rDoc.DecSizeRecalcLevel( nScTab );
274 }
275
ConvertHiddenFlags(SCTAB nScTab)276 void XclImpColRowSettings::ConvertHiddenFlags( SCTAB nScTab )
277 {
278 ScDocument& rDoc = GetDoc();
279 rDoc.IncSizeRecalcLevel( nScTab ); // #i116460# performance with many hidden rows
280
281 // hide the columns
282 for( SCCOL nScCol = 0; nScCol <= mnMaxCol; ++nScCol )
283 if( ::get_flag( maColFlags[ nScCol ], EXC_COLROW_HIDDEN ) )
284 rDoc.SetColHidden( nScCol, nScCol, nScTab, sal_True );
285
286 // hide remaining columns outside Excel's sheet limits
287 if( ::get_flag( maColFlags[ mnMaxCol ], EXC_COLROW_HIDDEN ) && (mnMaxCol < MAXCOL) )
288 rDoc.SetColHidden( mnMaxCol + 1, MAXCOL, nScTab, sal_True );
289
290 // #i38093# rows hidden by filter need extra flag
291 SCROW nFirstFilterScRow = SCROW_MAX;
292 SCROW nLastFilterScRow = SCROW_MAX;
293 if( GetBiff() == EXC_BIFF8 )
294 {
295 const XclImpAutoFilterData* pFilter = GetFilterManager().GetByTab( nScTab );
296 // #i70026# use IsFiltered() to set the CR_FILTERED flag for active filters only
297 if( pFilter && pFilter->IsActive() && pFilter->IsFiltered() )
298 {
299 nFirstFilterScRow = pFilter->StartRow();
300 nLastFilterScRow = pFilter->EndRow();
301 }
302 }
303
304 // hide the rows
305 for( SCROW nScRow = 0; nScRow <= mnLastScRow; ++nScRow )
306 {
307 if( ::get_flag( maRowFlags[ nScRow ], EXC_COLROW_HIDDEN ) )
308 {
309 // hide the row
310 rDoc.SetRowHidden(nScRow, nScRow, nScTab, true); // #i116460# SetRowHidden instead of ShowRow
311 // #i38093# rows hidden by filter need extra flag
312 if( (nFirstFilterScRow <= nScRow) && (nScRow <= nLastFilterScRow) )
313 rDoc.SetRowFiltered(nScRow, nScRow, nScTab, true);
314 }
315 }
316
317 // #i47438# if default row format is hidden, hide remaining rows
318 if( ::get_flag( mnDefRowFlags, EXC_DEFROW_HIDDEN ) && (mnLastScRow < MAXROW) )
319 rDoc.ShowRows( mnLastScRow + 1, MAXROW, nScTab, sal_False );
320
321 rDoc.DecSizeRecalcLevel( nScTab ); // #i116460# performance with many hidden rows
322 }
323
324