use insert function instead of for loop
[LibreOffice.git] / sc / source / filter / excel / colrowst.cxx
blobe194b7309d9bcdff761082ceadeded81e083cbc0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <colrowst.hxx>
22 #include <document.hxx>
23 #include <ftools.hxx>
24 #include <xltable.hxx>
25 #include <xistyle.hxx>
26 #include <excimp8.hxx>
27 #include <table.hxx>
29 XclImpColRowSettings::XclImpColRowSettings( const XclImpRoot& rRoot ) :
30 XclImpRoot( rRoot ),
31 maColWidths(0, rRoot.GetDoc().GetSheetLimits().GetMaxColCount(), 0),
32 maColFlags(0, rRoot.GetDoc().GetSheetLimits().GetMaxColCount(), ExcColRowFlags::NONE),
33 maRowHeights(0, rRoot.GetDoc().GetSheetLimits().GetMaxRowCount(), 0),
34 maRowFlags(0, rRoot.GetDoc().GetSheetLimits().GetMaxRowCount(), ExcColRowFlags::NONE),
35 maHiddenRows(0, rRoot.GetDoc().GetSheetLimits().GetMaxRowCount(), false),
36 mnLastScRow( -1 ),
37 mnDefWidth( STD_COL_WIDTH ),
38 mnDefHeight( ScGlobal::nStdRowHeight ),
39 mnDefRowFlags( EXC_DEFROW_DEFAULTFLAGS ),
40 mbHasStdWidthRec( false ),
41 mbHasDefHeight( false ),
42 mbDirty( true )
46 XclImpColRowSettings::~XclImpColRowSettings()
50 void XclImpColRowSettings::SetDefWidth( sal_uInt16 nDefWidth, bool bStdWidthRec )
52 if( bStdWidthRec )
54 // STANDARDWIDTH record overrides DEFCOLWIDTH record
55 mnDefWidth = nDefWidth;
56 mbHasStdWidthRec = true;
58 else if( !mbHasStdWidthRec )
60 // use DEFCOLWIDTH record only, if no STANDARDWIDTH record exists
61 mnDefWidth = nDefWidth;
65 void XclImpColRowSettings::SetWidthRange( SCCOL nCol1, SCCOL nCol2, sal_uInt16 nWidth )
67 ScDocument& rDoc = GetDoc();
68 nCol2 = ::std::min( nCol2, rDoc.MaxCol() );
69 if (nCol2 == 256)
70 // In BIFF8, the column range is 0-255, and the use of 256 probably
71 // means the range should extend to the max column if the loading app
72 // support columns beyond 255.
73 nCol2 = rDoc.MaxCol();
75 nCol1 = ::std::min( nCol1, nCol2 );
76 maColWidths.insert_back(nCol1, nCol2+1, nWidth);
78 // We need to apply flag values individually since all flag values are aggregated for each column.
79 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
80 ApplyColFlag(nCol, ExcColRowFlags::Used);
83 void XclImpColRowSettings::HideCol( SCCOL nCol )
85 if (!GetDoc().ValidCol(nCol))
86 return;
88 ApplyColFlag(nCol, ExcColRowFlags::Hidden);
91 void XclImpColRowSettings::HideColRange( SCCOL nCol1, SCCOL nCol2 )
93 nCol2 = ::std::min( nCol2, GetDoc().MaxCol() );
94 nCol1 = ::std::min( nCol1, nCol2 );
96 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
97 ApplyColFlag(nCol, ExcColRowFlags::Hidden);
100 void XclImpColRowSettings::SetDefHeight( sal_uInt16 nDefHeight, sal_uInt16 nFlags )
102 mnDefHeight = nDefHeight;
103 mnDefRowFlags = nFlags;
104 if( mnDefHeight == 0 )
106 mnDefHeight = ScGlobal::nStdRowHeight;
107 ::set_flag( mnDefRowFlags, EXC_DEFROW_HIDDEN );
109 mbHasDefHeight = true;
112 void XclImpColRowSettings::SetHeight( SCROW nScRow, sal_uInt16 nHeight )
114 if (!GetDoc().ValidRow(nScRow))
115 return;
117 sal_uInt16 nRawHeight = nHeight & EXC_ROW_HEIGHTMASK;
118 bool bDefHeight = ::get_flag( nHeight, EXC_ROW_FLAGDEFHEIGHT ) || (nRawHeight == 0);
119 maRowHeights.insert_back(nScRow, nScRow+1, nRawHeight);
120 ExcColRowFlags nFlagVal = ExcColRowFlags::NONE;
121 if (!maRowFlags.search(nScRow, nFlagVal).second)
122 return;
124 ::set_flag(nFlagVal, ExcColRowFlags::Used);
125 ::set_flag(nFlagVal, ExcColRowFlags::Default, bDefHeight);
127 maRowFlags.insert_back(nScRow, nScRow+1, nFlagVal);
129 if (nScRow > mnLastScRow)
130 mnLastScRow = nScRow;
133 void XclImpColRowSettings::SetRowSettings( SCROW nScRow, sal_uInt16 nHeight, sal_uInt16 nFlags )
135 if (!GetDoc().ValidRow(nScRow))
136 return;
138 SetHeight(nScRow, nHeight);
140 ExcColRowFlags nFlagVal = ExcColRowFlags::NONE;
141 if (!maRowFlags.search(nScRow, nFlagVal).second)
142 return;
144 if (::get_flag(nFlags, EXC_ROW_UNSYNCED))
145 ::set_flag(nFlagVal, ExcColRowFlags::Man);
147 maRowFlags.insert_back(nScRow, nScRow+1, nFlagVal);
149 if (::get_flag(nFlags, EXC_ROW_HIDDEN))
150 maHiddenRows.insert_back(nScRow, nScRow+1, true);
153 void XclImpColRowSettings::SetManualRowHeight( SCROW nScRow )
155 if (!GetDoc().ValidRow(nScRow))
156 return;
158 ExcColRowFlags nFlagVal = ExcColRowFlags::NONE;
159 if (!maRowFlags.search(nScRow, nFlagVal).second)
160 return;
162 nFlagVal |= ExcColRowFlags::Man;
163 maRowFlags.insert_back(nScRow, nScRow+1, nFlagVal);
166 void XclImpColRowSettings::SetDefaultXF( SCCOL nCol1, SCCOL nCol2, sal_uInt16 nXFIndex )
168 /* assign the default column formatting here to ensure that
169 explicit cell formatting is not overwritten. */
170 OSL_ENSURE( (nCol1 <= nCol2) && GetDoc().ValidCol( nCol2 ), "XclImpColRowSettings::SetDefaultXF - invalid column index" );
171 nCol2 = ::std::min( nCol2, GetDoc().MaxCol() );
172 nCol1 = ::std::min( nCol1, nCol2 );
173 XclImpXFRangeBuffer& rXFRangeBuffer = GetXFRangeBuffer();
174 for( SCCOL nCol = nCol1; nCol <= nCol2; ++nCol )
175 rXFRangeBuffer.SetColumnDefXF( nCol, nXFIndex );
178 void XclImpColRowSettings::Convert( SCTAB nScTab )
180 if( !mbDirty )
181 return;
183 ScDocument& rDoc = GetDoc();
185 // column widths ----------------------------------------------------------
187 maColWidths.build_tree();
188 for (SCCOL nCol = 0; nCol <= rDoc.MaxCol(); ++nCol)
190 sal_uInt16 nWidth = mnDefWidth;
191 if (GetColFlag(nCol, ExcColRowFlags::Used))
193 sal_uInt16 nTmp;
194 if (maColWidths.search_tree(nCol, nTmp).second)
195 nWidth = nTmp;
198 /* Hidden columns: remember hidden state, but do not set hidden state
199 in document here. Needed for #i11776#, no HIDDEN flags in the
200 document, until filters and outlines are inserted. */
201 if( nWidth == 0 )
203 ApplyColFlag(nCol, ExcColRowFlags::Hidden);
204 nWidth = mnDefWidth;
206 rDoc.SetColWidthOnly( nCol, nScTab, nWidth );
209 // row heights ------------------------------------------------------------
211 // #i54252# set default row height
212 rDoc.SetRowHeightOnly( 0, rDoc.MaxRow(), nScTab, mnDefHeight );
213 if( ::get_flag( mnDefRowFlags, EXC_DEFROW_UNSYNCED ) )
214 // first access to row flags, do not ask for old flags
215 rDoc.SetRowFlags( 0, rDoc.MaxRow(), nScTab, CRFlags::ManualSize );
217 maRowHeights.build_tree();
218 if (!maRowHeights.is_tree_valid())
219 return;
221 SCROW nPrevRow = -1;
222 ExcColRowFlags nPrevFlags = ExcColRowFlags::NONE;
223 for (const auto& [nRow, nFlags] : maRowFlags)
225 if (nPrevRow >= 0)
227 sal_uInt16 nHeight = 0;
229 if (nPrevFlags & ExcColRowFlags::Used)
231 if (nPrevFlags & ExcColRowFlags::Default)
233 nHeight = mnDefHeight;
234 rDoc.SetRowHeightOnly(nPrevRow, nRow-1, nScTab, nHeight);
236 else
238 for (SCROW i = nPrevRow; i <= nRow - 1; ++i)
240 SCROW nLast;
241 if (!maRowHeights.search_tree(i, nHeight, nullptr, &nLast).second)
243 // search failed for some reason
244 return;
247 if (nLast > nRow)
248 nLast = nRow;
250 rDoc.SetRowHeightOnly(i, nLast-1, nScTab, nHeight);
251 i = nLast-1;
255 if (nPrevFlags & ExcColRowFlags::Man)
256 rDoc.SetManualHeight(nPrevRow, nRow-1, nScTab, true);
258 else
260 nHeight = mnDefHeight;
261 rDoc.SetRowHeightOnly(nPrevRow, nRow-1, nScTab, nHeight);
265 nPrevRow = nRow;
266 nPrevFlags = nFlags;
269 mbDirty = false;
272 void XclImpColRowSettings::ConvertHiddenFlags( SCTAB nScTab )
274 ScDocument& rDoc = GetDoc();
276 // hide the columns
277 for( SCCOL nCol : rDoc.GetColumnsRange(nScTab, 0, rDoc.MaxCol()) )
278 if (GetColFlag(nCol, ExcColRowFlags::Hidden))
279 rDoc.ShowCol( nCol, nScTab, false );
281 // #i38093# rows hidden by filter need extra flag
282 SCROW nFirstFilterScRow = SCROW_MAX;
283 SCROW nLastFilterScRow = SCROW_MAX;
284 if( GetBiff() == EXC_BIFF8 )
286 const XclImpAutoFilterData* pFilter = GetFilterManager().GetByTab( nScTab );
287 // #i70026# use IsFiltered() to set the CRFlags::Filtered flag for active filters only
288 if( pFilter && pFilter->IsActive() && pFilter->IsFiltered() )
290 nFirstFilterScRow = pFilter->StartRow();
291 nLastFilterScRow = pFilter->EndRow();
295 // In case the excel row limit is lower than calc's, use the visibility of
296 // the last row and extend it to calc's last row.
297 SCROW nLastXLRow = GetRoot().GetXclMaxPos().Row();
298 if (nLastXLRow < rDoc.MaxRow())
300 bool bHidden = false;
301 if (!maHiddenRows.search(nLastXLRow, bHidden).second)
302 return;
304 maHiddenRows.insert_back(nLastXLRow, GetDoc().GetSheetLimits().GetMaxRowCount(), bHidden);
307 SCROW nPrevRow = -1;
308 bool bPrevHidden = false;
309 for (const auto& [nRow, bHidden] : maHiddenRows)
311 if (nPrevRow >= 0)
313 if (bPrevHidden)
315 rDoc.SetRowHidden(nPrevRow, nRow-1, nScTab, true);
316 // #i38093# rows hidden by filter need extra flag
317 if (nFirstFilterScRow <= nPrevRow && nPrevRow <= nLastFilterScRow)
319 SCROW nLast = ::std::min(nRow-1, nLastFilterScRow);
320 rDoc.SetRowFiltered(nPrevRow, nLast, nScTab, true);
325 nPrevRow = nRow;
326 bPrevHidden = bHidden;
329 // #i47438# if default row format is hidden, hide remaining rows
330 if( ::get_flag( mnDefRowFlags, EXC_DEFROW_HIDDEN ) && (mnLastScRow < rDoc.MaxRow()) )
331 rDoc.ShowRows( mnLastScRow + 1, rDoc.MaxRow(), nScTab, false );
334 void XclImpColRowSettings::ApplyColFlag(SCCOL nCol, ExcColRowFlags nNewVal)
336 // Get the original flag value.
337 ExcColRowFlags nFlagVal = ExcColRowFlags::NONE;
338 std::pair<ColRowFlagsType::const_iterator,bool> r = maColFlags.search(nCol, nFlagVal);
339 if (!r.second)
340 // Search failed.
341 return;
343 ::set_flag(nFlagVal, nNewVal);
345 // Re-insert the flag value.
346 maColFlags.insert(r.first, nCol, nCol+1, nFlagVal);
349 bool XclImpColRowSettings::GetColFlag(SCCOL nCol, ExcColRowFlags nMask) const
351 ExcColRowFlags nFlagVal = ExcColRowFlags::NONE;
352 if (!maColFlags.search(nCol, nFlagVal).second)
353 return false;
354 // Search failed.
356 return bool(nFlagVal & nMask);
359 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */