xref: /trunk/main/sc/source/filter/excel/colrowst.cxx (revision b77af630)
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