/src/libreoffice/sc/source/ui/docshell/docsh.cxx
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <sal/config.h> |
21 | | |
22 | | #include <docsh.hxx> |
23 | | |
24 | | #include <config_features.h> |
25 | | #include <scitems.hxx> |
26 | | #include <sc.hrc> |
27 | | #include <vcl/errinf.hxx> |
28 | | #include <editeng/justifyitem.hxx> |
29 | | #include <comphelper/fileformat.h> |
30 | | #include <comphelper/classids.hxx> |
31 | | #include <comphelper/propertyvalue.hxx> |
32 | | #include <formula/errorcodes.hxx> |
33 | | #include <vcl/stdtext.hxx> |
34 | | #include <vcl/syswin.hxx> |
35 | | #include <vcl/svapp.hxx> |
36 | | #include <vcl/virdev.hxx> |
37 | | #include <vcl/weld.hxx> |
38 | | #include <rtl/bootstrap.hxx> |
39 | | #include <rtl/tencinfo.h> |
40 | | #include <sal/log.hxx> |
41 | | #include <svl/PasswordHelper.hxx> |
42 | | #include <sfx2/app.hxx> |
43 | | #include <sfx2/bindings.hxx> |
44 | | #include <sfx2/dinfdlg.hxx> |
45 | | #include <sfx2/docfile.hxx> |
46 | | #include <sfx2/event.hxx> |
47 | | #include <sfx2/docfilt.hxx> |
48 | | #include <sfx2/lokhelper.hxx> |
49 | | #include <sfx2/objface.hxx> |
50 | | #include <sfx2/viewfrm.hxx> |
51 | | #include <sfx2/infobar.hxx> |
52 | | #include <svl/documentlockfile.hxx> |
53 | | #include <svl/fstathelper.hxx> |
54 | | #include <svl/sharecontrolfile.hxx> |
55 | | #include <svl/urihelper.hxx> |
56 | | #include <osl/file.hxx> |
57 | | #include <chgtrack.hxx> |
58 | | #include <chgviset.hxx> |
59 | | #include <com/sun/star/awt/Key.hpp> |
60 | | #include <com/sun/star/awt/KeyModifier.hpp> |
61 | | #include <com/sun/star/container/XContentEnumerationAccess.hpp> |
62 | | #include <com/sun/star/document/UpdateDocMode.hpp> |
63 | | #include <com/sun/star/script/vba/VBAEventId.hpp> |
64 | | #include <com/sun/star/script/vba/VBAScriptEventId.hpp> |
65 | | #include <com/sun/star/script/vba/XVBAEventProcessor.hpp> |
66 | | #include <com/sun/star/script/vba/XVBAScriptListener.hpp> |
67 | | #include <com/sun/star/script/vba/XVBACompatibility.hpp> |
68 | | #include <com/sun/star/sheet/XSpreadsheetView.hpp> |
69 | | #include <com/sun/star/task/XJob.hpp> |
70 | | #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp> |
71 | | #include <com/sun/star/ui/XAcceleratorConfiguration.hpp> |
72 | | #include <com/sun/star/util/VetoException.hpp> |
73 | | #include <com/sun/star/lang/XSingleComponentFactory.hpp> |
74 | | #include <ooo/vba/excel/XWorkbook.hpp> |
75 | | #include <comphelper/diagnose_ex.hxx> |
76 | | |
77 | | #include <config_folders.h> |
78 | | |
79 | | #include <scabstdlg.hxx> |
80 | | #include <sot/formats.hxx> |
81 | | #include <svx/compatflags.hxx> |
82 | | #include <svx/dialogs.hrc> |
83 | | #include <svx/svdpagv.hxx> |
84 | | #include <svx/svdpage.hxx> |
85 | | #include <docmodel/theme/Theme.hxx> |
86 | | |
87 | | #include <inputopt.hxx> |
88 | | #include <formulacell.hxx> |
89 | | #include <global.hxx> |
90 | | #include <filter.hxx> |
91 | | #include <scmod.hxx> |
92 | | #include <tabvwsh.hxx> |
93 | | #include <docfunc.hxx> |
94 | | #include <imoptdlg.hxx> |
95 | | #include <impex.hxx> |
96 | | #include <scresid.hxx> |
97 | | #include <strings.hrc> |
98 | | #include <globstr.hrc> |
99 | | #include <scerrors.hxx> |
100 | | #include <brdcst.hxx> |
101 | | #include <stlpool.hxx> |
102 | | #include <autostyl.hxx> |
103 | | #include <attrib.hxx> |
104 | | #include <asciiopt.hxx> |
105 | | #include <progress.hxx> |
106 | | #include <pntlock.hxx> |
107 | | #include <docuno.hxx> |
108 | | #include <appoptio.hxx> |
109 | | #include <formulaopt.hxx> |
110 | | #include <scdll.hxx> |
111 | | #include <detdata.hxx> |
112 | | #include <printfun.hxx> |
113 | | #include <dociter.hxx> |
114 | | #include <cellform.hxx> |
115 | | #include <chartlis.hxx> |
116 | | #include <hints.hxx> |
117 | | #include <xmlwrap.hxx> |
118 | | #include <drwlayer.hxx> |
119 | | #include <dbdata.hxx> |
120 | | #include <scextopt.hxx> |
121 | | #include <compiler.hxx> |
122 | | #include <warnpassword.hxx> |
123 | | #include <sheetdata.hxx> |
124 | | #include <table.hxx> |
125 | | #include <tabprotection.hxx> |
126 | | #include <docparam.hxx> |
127 | | #include "docshimp.hxx" |
128 | | #include <sizedev.hxx> |
129 | | #include <undomanager.hxx> |
130 | | #include <refreshtimerprotector.hxx> |
131 | | |
132 | | #include <officecfg/Office/Calc.hxx> |
133 | | #include <comphelper/processfactory.hxx> |
134 | | #include <comphelper/string.hxx> |
135 | | #include <unotools/configmgr.hxx> |
136 | | #include <unotools/mediadescriptor.hxx> |
137 | | #include <unotools/tempfile.hxx> |
138 | | #include <unotools/ucbstreamhelper.hxx> |
139 | | #include <uiitems.hxx> |
140 | | #include <dpobject.hxx> |
141 | | #include <markdata.hxx> |
142 | | #include <docoptio.hxx> |
143 | | #include <orcusfilters.hxx> |
144 | | #include <datastream.hxx> |
145 | | #include <documentlinkmgr.hxx> |
146 | | #include <refupdatecontext.hxx> |
147 | | #include <DocumentModelAccessor.hxx> |
148 | | |
149 | | #include <memory> |
150 | | #include <vector> |
151 | | |
152 | | #include <comphelper/lok.hxx> |
153 | | #include <svtools/sfxecode.hxx> |
154 | | #include <unotools/pathoptions.hxx> |
155 | | |
156 | | using namespace com::sun::star; |
157 | | using ::com::sun::star::uno::Reference; |
158 | | using ::com::sun::star::lang::XMultiServiceFactory; |
159 | | using std::shared_ptr; |
160 | | using ::std::vector; |
161 | | |
162 | | // Filter names (like in sclib.cxx) |
163 | | |
164 | | constexpr OUStringLiteral pFilterSc50 = u"StarCalc 5.0"; |
165 | | const char pFilterXML[] = "StarOffice XML (Calc)"; |
166 | | constexpr OUString pFilterLotus = u"Lotus"_ustr; |
167 | | const char pFilterQPro6[] = "Quattro Pro 6.0"; |
168 | | const char16_t pFilterExcel4[] = u"MS Excel 4.0"; |
169 | | const char16_t pFilterEx4Temp[] = u"MS Excel 4.0 Vorlage/Template"; |
170 | | const char pFilterExcel5[] = "MS Excel 5.0/95"; |
171 | | const char pFilterEx5Temp[] = "MS Excel 5.0/95 Vorlage/Template"; |
172 | | const char pFilterExcel95[] = "MS Excel 95"; |
173 | | const char pFilterEx95Temp[] = "MS Excel 95 Vorlage/Template"; |
174 | | const char pFilterExcel97[] = "MS Excel 97"; |
175 | | const char pFilterEx97Temp[] = "MS Excel 97 Vorlage/Template"; |
176 | | constexpr OUString pFilterDBase = u"dBase"_ustr; |
177 | | constexpr OUString pFilterDif = u"DIF"_ustr; |
178 | | const char16_t pFilterSylk[] = u"SYLK"; |
179 | | constexpr OUString pFilterHtml = u"HTML (StarCalc)"_ustr; |
180 | | constexpr OUString pFilterHtmlWebQ = u"calc_HTML_WebQuery"_ustr; |
181 | | const char16_t pFilterRtf[] = u"Rich Text Format (StarCalc)"; |
182 | | |
183 | | #define ShellClass_ScDocShell |
184 | | #include <scslots.hxx> |
185 | | |
186 | | SFX_IMPL_INTERFACE(ScDocShell,SfxObjectShell) |
187 | | |
188 | | void ScDocShell::InitInterface_Impl() |
189 | 11 | { |
190 | 11 | } |
191 | | |
192 | | // GlobalName of the current version: |
193 | | SFX_IMPL_OBJECTFACTORY( ScDocShell, SvGlobalName(SO3_SC_CLASSID), u"scalc"_ustr ) |
194 | | |
195 | | |
196 | | void ScDocShell::FillClass( SvGlobalName* pClassName, |
197 | | SotClipboardFormatId* pFormat, |
198 | | OUString* pFullTypeName, |
199 | | sal_Int32 nFileFormat, |
200 | | bool bTemplate /* = false */) const |
201 | 65.6k | { |
202 | 65.6k | if ( nFileFormat == SOFFICE_FILEFORMAT_60 ) |
203 | 0 | { |
204 | 0 | *pClassName = SvGlobalName( SO3_SC_CLASSID_60 ); |
205 | 0 | *pFormat = SotClipboardFormatId::STARCALC_60; |
206 | 0 | *pFullTypeName = ScResId( SCSTR_LONG_SCDOC_NAME_60 ); |
207 | 0 | } |
208 | 65.6k | else if ( nFileFormat == SOFFICE_FILEFORMAT_8 ) |
209 | 65.6k | { |
210 | 65.6k | *pClassName = SvGlobalName( SO3_SC_CLASSID_60 ); |
211 | 65.6k | *pFormat = bTemplate ? SotClipboardFormatId::STARCALC_8_TEMPLATE : SotClipboardFormatId::STARCALC_8; |
212 | 65.6k | *pFullTypeName = ScResId( SCSTR_LONG_SCDOC_NAME_80 ); |
213 | 65.6k | } |
214 | 0 | else |
215 | 0 | { |
216 | 0 | OSL_FAIL("Which version?"); |
217 | 0 | } |
218 | 65.6k | } |
219 | | |
220 | | std::set<Color> ScDocShell::GetDocColors() |
221 | 0 | { |
222 | 0 | return m_pDocument->GetDocColors(); |
223 | 0 | } |
224 | | |
225 | | std::shared_ptr<sfx::IDocumentModelAccessor> ScDocShell::GetDocumentModelAccessor() const |
226 | 0 | { |
227 | 0 | std::shared_ptr<sfx::IDocumentModelAccessor> pReturn; |
228 | 0 | pReturn.reset(new sc::DocumentModelAccessor(m_pDocument)); |
229 | 0 | return pReturn; |
230 | 0 | } |
231 | | |
232 | | std::shared_ptr<model::ColorSet> ScDocShell::GetThemeColors() |
233 | 0 | { |
234 | 0 | ScTabViewShell* pShell = GetBestViewShell(); |
235 | 0 | if (!pShell) |
236 | 0 | return {}; |
237 | | |
238 | 0 | SdrModel* pSdrModel = GetDocument().GetDrawLayer(); |
239 | 0 | if (!pSdrModel) |
240 | 0 | return {}; |
241 | | |
242 | 0 | auto const& pTheme = pSdrModel->getTheme(); |
243 | 0 | if (!pTheme) |
244 | 0 | return {}; |
245 | | |
246 | 0 | return pTheme->getColorSet(); |
247 | 0 | } |
248 | | |
249 | | void ScDocShell::DoEnterHandler() |
250 | 0 | { |
251 | 0 | ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); |
252 | 0 | if (pViewSh && &pViewSh->GetViewData().GetDocShell() == this) |
253 | 0 | ScModule::get()->InputEnterHandler(); |
254 | 0 | } |
255 | | |
256 | | SCTAB ScDocShell::GetSaveTab() |
257 | 0 | { |
258 | 0 | SCTAB nTab = 0; |
259 | 0 | ScTabViewShell* pSh = GetBestViewShell(); |
260 | 0 | if (pSh) |
261 | 0 | { |
262 | 0 | const ScMarkData& rMark = pSh->GetViewData().GetMarkData(); |
263 | 0 | nTab = rMark.GetFirstSelected(); |
264 | 0 | } |
265 | 0 | return nTab; |
266 | 0 | } |
267 | | |
268 | | HiddenInformation ScDocShell::GetHiddenInformationState( HiddenInformation nStates ) |
269 | 0 | { |
270 | | // get global state like HiddenInformation::DOCUMENTVERSIONS |
271 | 0 | HiddenInformation nState = SfxObjectShell::GetHiddenInformationState( nStates ); |
272 | |
|
273 | 0 | if ( nStates & HiddenInformation::RECORDEDCHANGES ) |
274 | 0 | { |
275 | 0 | if ( m_pDocument->GetChangeTrack() && m_pDocument->GetChangeTrack()->GetFirst() ) |
276 | 0 | nState |= HiddenInformation::RECORDEDCHANGES; |
277 | 0 | } |
278 | 0 | if ( nStates & HiddenInformation::NOTES ) |
279 | 0 | { |
280 | 0 | SCTAB nTableCount = m_pDocument->GetTableCount(); |
281 | 0 | bool bFound = false; |
282 | 0 | for (SCTAB nTab = 0; nTab < nTableCount && !bFound; ++nTab) |
283 | 0 | { |
284 | 0 | if (m_pDocument->HasTabNotes(nTab)) //TODO: |
285 | 0 | bFound = true; |
286 | 0 | } |
287 | |
|
288 | 0 | if (bFound) |
289 | 0 | nState |= HiddenInformation::NOTES; |
290 | 0 | } |
291 | |
|
292 | 0 | return nState; |
293 | 0 | } |
294 | | |
295 | | void ScDocShell::BeforeXMLLoading() |
296 | 44.6k | { |
297 | 44.6k | m_pDocument->EnableIdle(false); |
298 | | |
299 | | // prevent unnecessary broadcasts and updates |
300 | 44.6k | OSL_ENSURE(m_pModificator == nullptr, "The Modificator should not exist"); |
301 | 44.6k | m_pModificator.reset( new ScDocShellModificator( *this ) ); |
302 | | |
303 | 44.6k | m_pDocument->SetImportingXML( true ); |
304 | 44.6k | m_pDocument->EnableExecuteLink( false ); // #i101304# to be safe, prevent nested loading from external references |
305 | 44.6k | m_pDocument->EnableUndo( false ); |
306 | | // prevent unnecessary broadcasts and "half way listeners" |
307 | 44.6k | m_pDocument->SetInsertingFromOtherDoc( true ); |
308 | 44.6k | } |
309 | | |
310 | | void ScDocShell::AfterXMLLoading(bool bRet) |
311 | 13.9k | { |
312 | 13.9k | if (GetCreateMode() != SfxObjectCreateMode::ORGANIZER) |
313 | 13.9k | { |
314 | 13.9k | UpdateLinks(); |
315 | | // don't prevent establishing of listeners anymore |
316 | 13.9k | m_pDocument->SetInsertingFromOtherDoc( false ); |
317 | 13.9k | if ( bRet ) |
318 | 13.9k | { |
319 | 13.9k | ScChartListenerCollection* pChartListener = m_pDocument->GetChartListenerCollection(); |
320 | 13.9k | if (pChartListener) |
321 | 13.9k | pChartListener->UpdateDirtyCharts(); |
322 | | |
323 | | // #95582#; set the table names of linked tables to the new path |
324 | 13.9k | SCTAB nTabCount = m_pDocument->GetTableCount(); |
325 | 32.6k | for (SCTAB i = 0; i < nTabCount; ++i) |
326 | 18.7k | { |
327 | 18.7k | if (m_pDocument->IsLinked( i )) |
328 | 0 | { |
329 | 0 | OUString aName; |
330 | 0 | m_pDocument->GetName(i, aName); |
331 | 0 | OUString aLinkTabName = m_pDocument->GetLinkTab(i); |
332 | 0 | sal_Int32 nLinkTabNameLength = aLinkTabName.getLength(); |
333 | 0 | sal_Int32 nNameLength = aName.getLength(); |
334 | 0 | if (nLinkTabNameLength < nNameLength) |
335 | 0 | { |
336 | | |
337 | | // remove the quotes on begin and end of the docname and restore the escaped quotes |
338 | 0 | const sal_Unicode* pNameBuffer = aName.getStr(); |
339 | 0 | if ( *pNameBuffer == '\'' && // all docnames have to have a ' character on the first pos |
340 | 0 | ScGlobal::UnicodeStrChr( pNameBuffer, SC_COMPILER_FILE_TAB_SEP ) ) |
341 | 0 | { |
342 | 0 | OUStringBuffer aDocURLBuffer; |
343 | 0 | bool bQuote = true; // Document name is always quoted |
344 | 0 | ++pNameBuffer; |
345 | 0 | while ( bQuote && *pNameBuffer ) |
346 | 0 | { |
347 | 0 | if ( *pNameBuffer == '\'' && *(pNameBuffer-1) != '\\' ) |
348 | 0 | bQuote = false; |
349 | 0 | else if( *pNameBuffer != '\\' || *(pNameBuffer+1) != '\'' ) |
350 | 0 | aDocURLBuffer.append(*pNameBuffer); // If escaped quote: only quote in the name |
351 | 0 | ++pNameBuffer; |
352 | 0 | } |
353 | |
|
354 | 0 | if( *pNameBuffer == SC_COMPILER_FILE_TAB_SEP ) // after the last quote of the docname should be the # char |
355 | 0 | { |
356 | 0 | sal_Int32 nIndex = nNameLength - nLinkTabNameLength; |
357 | 0 | INetURLObject aINetURLObject(aDocURLBuffer); |
358 | 0 | if(aName.match( aLinkTabName, nIndex) && |
359 | 0 | (aName[nIndex - 1] == '#') && // before the table name should be the # char |
360 | 0 | !aINetURLObject.HasError()) // the docname should be a valid URL |
361 | 0 | { |
362 | 0 | aName = ScGlobal::GetDocTabName( m_pDocument->GetLinkDoc( i ), m_pDocument->GetLinkTab( i ) ); |
363 | 0 | m_pDocument->RenameTab(i, aName, true/*bExternalDocument*/); |
364 | 0 | } |
365 | | // else; nothing has to happen, because it is a user given name |
366 | 0 | } |
367 | | // else; nothing has to happen, because it is a user given name |
368 | 0 | } |
369 | | // else; nothing has to happen, because it is a user given name |
370 | 0 | } |
371 | | // else; nothing has to happen, because it is a user given name |
372 | 0 | } |
373 | 18.7k | } |
374 | | |
375 | | // #i94570# DataPilot table names have to be unique, or the tables can't be accessed by API. |
376 | | // If no name (or an invalid name, skipped in ScXMLDataPilotTableContext::EndElement) was set, create a new name. |
377 | 13.9k | ScDPCollection* pDPCollection = m_pDocument->GetDPCollection(); |
378 | 13.9k | if ( pDPCollection ) |
379 | 13.9k | { |
380 | 13.9k | size_t nDPCount = pDPCollection->GetCount(); |
381 | 13.9k | for (size_t nDP=0; nDP<nDPCount; ++nDP) |
382 | 0 | { |
383 | 0 | ScDPObject& rDPObj = (*pDPCollection)[nDP]; |
384 | 0 | if (rDPObj.GetName().isEmpty()) |
385 | 0 | rDPObj.SetName( pDPCollection->CreateNewName() ); |
386 | 0 | } |
387 | 13.9k | } |
388 | 13.9k | } |
389 | 13.9k | } |
390 | 0 | else |
391 | 0 | m_pDocument->SetInsertingFromOtherDoc( false ); |
392 | | |
393 | 13.9k | m_pDocument->SetImportingXML( false ); |
394 | 13.9k | m_pDocument->EnableExecuteLink( true ); |
395 | 13.9k | m_pDocument->EnableUndo( true ); |
396 | 13.9k | m_bIsEmpty = false; |
397 | | |
398 | 13.9k | if (m_pModificator) |
399 | 13.9k | { |
400 | 13.9k | ScDocument::HardRecalcState eRecalcState = m_pDocument->GetHardRecalcState(); |
401 | | // Temporarily set hard-recalc to prevent calling |
402 | | // ScFormulaCell::Notify() during destruction of the Modificator which |
403 | | // will set the cells dirty. |
404 | 13.9k | if (eRecalcState == ScDocument::HardRecalcState::OFF) |
405 | 13.9k | m_pDocument->SetHardRecalcState(ScDocument::HardRecalcState::TEMPORARY); |
406 | 13.9k | m_pModificator.reset(); |
407 | 13.9k | m_pDocument->SetHardRecalcState(eRecalcState); |
408 | 13.9k | } |
409 | 0 | else |
410 | 0 | { |
411 | 0 | OSL_FAIL("The Modificator should exist"); |
412 | 0 | } |
413 | | |
414 | 13.9k | m_pDocument->EnableIdle(true); |
415 | 13.9k | } |
416 | | |
417 | | namespace { |
418 | | |
419 | | class LoadMediumGuard |
420 | | { |
421 | | public: |
422 | | explicit LoadMediumGuard(ScDocument* pDoc) : |
423 | 0 | mpDoc(pDoc) |
424 | 0 | { |
425 | 0 | mpDoc->SetLoadingMedium(true); |
426 | 0 | } |
427 | | |
428 | | ~LoadMediumGuard() |
429 | 0 | { |
430 | 0 | mpDoc->SetLoadingMedium(false); |
431 | 0 | } |
432 | | private: |
433 | | ScDocument* mpDoc; |
434 | | }; |
435 | | |
436 | | void processDataStream( ScDocShell& rShell, const sc::ImportPostProcessData& rData ) |
437 | 0 | { |
438 | 0 | if (!rData.mpDataStream) |
439 | 0 | return; |
440 | | |
441 | 0 | const sc::ImportPostProcessData::DataStream& r = *rData.mpDataStream; |
442 | 0 | if (!r.maRange.IsValid()) |
443 | 0 | return; |
444 | | |
445 | | // Break the streamed range into the top range and the height limit. A |
446 | | // height limit of 0 means unlimited i.e. the streamed data will go all |
447 | | // the way to the last row. |
448 | | |
449 | 0 | ScRange aTopRange = r.maRange; |
450 | 0 | aTopRange.aEnd.SetRow(aTopRange.aStart.Row()); |
451 | 0 | sal_Int32 nLimit = r.maRange.aEnd.Row() - r.maRange.aStart.Row() + 1; |
452 | 0 | if (r.maRange.aEnd.Row() == rShell.GetDocument().MaxRow()) |
453 | | // Unlimited range. |
454 | 0 | nLimit = 0; |
455 | |
|
456 | 0 | sc::DataStream::MoveType eMove = |
457 | 0 | r.meInsertPos == sc::ImportPostProcessData::DataStream::InsertTop ? |
458 | 0 | sc::DataStream::MOVE_DOWN : sc::DataStream::RANGE_DOWN; |
459 | |
|
460 | 0 | sc::DataStream* pStrm = new sc::DataStream(&rShell, r.maURL, aTopRange, nLimit, eMove); |
461 | 0 | pStrm->SetRefreshOnEmptyLine(r.mbRefreshOnEmpty); |
462 | 0 | sc::DocumentLinkManager& rMgr = rShell.GetDocument().GetDocLinkManager(); |
463 | 0 | rMgr.setDataStream(pStrm); |
464 | 0 | } |
465 | | |
466 | | class MessageWithCheck : public weld::MessageDialogController |
467 | | { |
468 | | private: |
469 | | std::unique_ptr<weld::CheckButton> m_xWarningOnBox; |
470 | | public: |
471 | | MessageWithCheck(weld::Window *pParent, const OUString& rUIFile, const OUString& rDialogId) |
472 | 0 | : MessageDialogController(pParent, rUIFile, rDialogId, u"ask"_ustr) |
473 | 0 | , m_xWarningOnBox(m_xBuilder->weld_check_button(u"ask"_ustr)) |
474 | 0 | { |
475 | 0 | } |
476 | 0 | bool get_active() const { return m_xWarningOnBox->get_active(); } |
477 | 0 | void hide_ask() const { m_xWarningOnBox->set_visible(false); }; |
478 | | }; |
479 | | |
480 | | #if HAVE_FEATURE_SCRIPTING |
481 | | class VBAScriptListener : public ::cppu::WeakImplHelper< css::script::vba::XVBAScriptListener > |
482 | | { |
483 | | private: |
484 | | ScDocShell* m_pDocSh; |
485 | | public: |
486 | | VBAScriptListener(ScDocShell* pDocSh) : m_pDocSh(pDocSh) |
487 | | { |
488 | | } |
489 | | |
490 | | // XVBAScriptListener |
491 | | virtual void SAL_CALL notifyVBAScriptEvent( const ::css::script::vba::VBAScriptEvent& aEvent ) override |
492 | | { |
493 | | if (aEvent.Identifier == script::vba::VBAScriptEventId::SCRIPT_STOPPED && |
494 | | m_pDocSh->GetClipData().is()) |
495 | | { |
496 | | m_pDocSh->SetClipData(uno::Reference<datatransfer::XTransferable2>()); |
497 | | } |
498 | | } |
499 | | |
500 | | // XEventListener |
501 | | virtual void SAL_CALL disposing( const ::css::lang::EventObject& /*Source*/ ) override |
502 | | { |
503 | | } |
504 | | }; |
505 | | #endif |
506 | | |
507 | | } |
508 | | |
509 | | bool ScDocShell::GetRecalcRowHeightsMode() |
510 | 15.2k | { |
511 | 15.2k | const ScRecalcOptions nRecalcMode = static_cast<ScRecalcOptions>( |
512 | 15.2k | officecfg::Office::Calc::Formula::Load::RecalcOptimalRowHeightMode::get()); |
513 | | |
514 | 15.2k | bool bHardRecalc = false; |
515 | 15.2k | switch (nRecalcMode) |
516 | 15.2k | { |
517 | 0 | case RECALC_ASK: |
518 | 0 | { |
519 | 0 | if (m_pDocument->IsUserInteractionEnabled()) |
520 | 0 | { |
521 | | // Ask if the user wants to perform full re-calculation. |
522 | 0 | MessageWithCheck aQueryBox(ScDocShell::GetActiveDialogParent(), |
523 | 0 | u"modules/scalc/ui/recalcquerydialog.ui"_ustr, |
524 | 0 | u"RecalcQueryDialog"_ustr); |
525 | 0 | aQueryBox.set_primary_text(ScResId(STR_QUERY_OPT_ROW_HEIGHT_RECALC_ONLOAD)); |
526 | 0 | aQueryBox.set_default_response(RET_YES); |
527 | |
|
528 | 0 | if (officecfg::Office::Calc::Formula::Load::RecalcOptimalRowHeightMode::isReadOnly()) |
529 | 0 | aQueryBox.hide_ask(); |
530 | |
|
531 | 0 | bHardRecalc = aQueryBox.run() == RET_YES; |
532 | |
|
533 | 0 | if (aQueryBox.get_active()) |
534 | 0 | { |
535 | | // Always perform selected action in the future. |
536 | 0 | std::shared_ptr<comphelper::ConfigurationChanges> batch( |
537 | 0 | comphelper::ConfigurationChanges::create()); |
538 | 0 | officecfg::Office::Calc::Formula::Load::RecalcOptimalRowHeightMode::set( |
539 | 0 | bHardRecalc ? static_cast<sal_Int32>(RECALC_ALWAYS) |
540 | 0 | : static_cast<sal_Int32>(RECALC_NEVER), |
541 | 0 | batch); |
542 | |
|
543 | 0 | ScModule* mod = ScModule::get(); |
544 | 0 | ScFormulaOptions aOpt = mod->GetFormulaOptions(); |
545 | 0 | aOpt.SetReCalcOptiRowHeights(bHardRecalc ? RECALC_ALWAYS : RECALC_NEVER); |
546 | 0 | mod->SetFormulaOptions(aOpt); |
547 | |
|
548 | 0 | batch->commit(); |
549 | 0 | } |
550 | 0 | } |
551 | 0 | } |
552 | 0 | break; |
553 | 15.2k | case RECALC_ALWAYS: |
554 | 15.2k | bHardRecalc = true; |
555 | 15.2k | break; |
556 | 0 | case RECALC_NEVER: |
557 | 0 | bHardRecalc = false; |
558 | 0 | break; |
559 | 0 | default: |
560 | 0 | SAL_WARN("sc", "unknown optimal row height recalc option!"); |
561 | 15.2k | } |
562 | | |
563 | 15.2k | return bHardRecalc; |
564 | 15.2k | } |
565 | | |
566 | | bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const css::uno::Reference< css::embed::XStorage >& xStor ) |
567 | 0 | { |
568 | 0 | LoadMediumGuard aLoadGuard(m_pDocument.get()); |
569 | | |
570 | | // MacroCallMode is no longer needed, state is kept in SfxObjectShell now |
571 | | |
572 | | // no Seek(0) here - always loading from storage, GetInStream must not be called |
573 | |
|
574 | 0 | BeforeXMLLoading(); |
575 | |
|
576 | 0 | ScXMLImportWrapper aImport(*this, pLoadMedium, xStor); |
577 | |
|
578 | 0 | bool bRet = false; |
579 | 0 | ErrCodeMsg nError = ERRCODE_NONE; |
580 | 0 | m_pDocument->LockAdjustHeight(); |
581 | 0 | if (GetCreateMode() == SfxObjectCreateMode::ORGANIZER) |
582 | 0 | bRet = aImport.Import(ImportFlags::Styles, nError); |
583 | 0 | else |
584 | 0 | bRet = aImport.Import(ImportFlags::All, nError); |
585 | |
|
586 | 0 | if ( nError ) |
587 | 0 | pLoadMedium->SetError(nError); |
588 | |
|
589 | 0 | processDataStream(*this, aImport.GetImportPostProcessData()); |
590 | | |
591 | | //if the document was not generated by LibreOffice, do hard recalc in case some other document |
592 | | //generator saved cached formula results that differ from LibreOffice's calculated results or |
593 | | //did not use cached formula results. |
594 | 0 | uno::Reference<document::XDocumentProperties> xDocProps = GetModel()->getDocumentProperties(); |
595 | |
|
596 | 0 | ScRecalcOptions nRecalcMode = |
597 | 0 | static_cast<ScRecalcOptions>(officecfg::Office::Calc::Formula::Load::ODFRecalcMode::get()); |
598 | |
|
599 | 0 | bool bHardRecalc = false; |
600 | 0 | if (nRecalcMode == RECALC_ASK) |
601 | 0 | { |
602 | 0 | OUString sProductName(utl::ConfigManager::getProductName()); |
603 | 0 | if (m_pDocument->IsUserInteractionEnabled() && xDocProps->getGenerator().indexOf(sProductName) == -1) |
604 | 0 | { |
605 | | // Generator is not LibreOffice. Ask if the user wants to perform |
606 | | // full re-calculation. |
607 | 0 | MessageWithCheck aQueryBox(GetActiveDialogParent(), |
608 | 0 | u"modules/scalc/ui/recalcquerydialog.ui"_ustr, u"RecalcQueryDialog"_ustr); |
609 | 0 | aQueryBox.set_primary_text(ScResId(STR_QUERY_FORMULA_RECALC_ONLOAD_ODS)); |
610 | 0 | aQueryBox.set_default_response(RET_YES); |
611 | |
|
612 | 0 | if ( officecfg::Office::Calc::Formula::Load::OOXMLRecalcMode::isReadOnly() ) |
613 | 0 | aQueryBox.hide_ask(); |
614 | |
|
615 | 0 | bHardRecalc = aQueryBox.run() == RET_YES; |
616 | |
|
617 | 0 | if (aQueryBox.get_active()) |
618 | 0 | { |
619 | | // Always perform selected action in the future. |
620 | 0 | std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create()); |
621 | 0 | officecfg::Office::Calc::Formula::Load::ODFRecalcMode::set(sal_Int32(0), batch); |
622 | 0 | ScModule* mod = ScModule::get(); |
623 | 0 | ScFormulaOptions aOpt = mod->GetFormulaOptions(); |
624 | 0 | aOpt.SetODFRecalcOptions(bHardRecalc ? RECALC_ALWAYS : RECALC_NEVER); |
625 | | /* XXX is this really supposed to set the ScModule options? |
626 | | * Not the ScDocShell options? */ |
627 | 0 | mod->SetFormulaOptions(aOpt); |
628 | |
|
629 | 0 | batch->commit(); |
630 | 0 | } |
631 | 0 | } |
632 | 0 | } |
633 | 0 | else if (nRecalcMode == RECALC_ALWAYS) |
634 | 0 | bHardRecalc = true; |
635 | |
|
636 | 0 | if (bHardRecalc) |
637 | 0 | DoHardRecalc(); |
638 | 0 | else |
639 | 0 | { |
640 | | // still need to recalc volatile formula cells. |
641 | 0 | m_pDocument->Broadcast(ScHint(SfxHintId::ScDataChanged, BCA_BRDCST_ALWAYS)); |
642 | 0 | } |
643 | |
|
644 | 0 | AfterXMLLoading(bRet); |
645 | |
|
646 | 0 | m_pDocument->UnlockAdjustHeight(); |
647 | 0 | return bRet; |
648 | 0 | } |
649 | | |
650 | | bool ScDocShell::SaveXML( SfxMedium* pSaveMedium, const css::uno::Reference< css::embed::XStorage >& xStor ) |
651 | 0 | { |
652 | 0 | m_pDocument->EnableIdle(false); |
653 | |
|
654 | 0 | ScXMLImportWrapper aImport(*this, pSaveMedium, xStor); |
655 | 0 | bool bRet(false); |
656 | 0 | if (GetCreateMode() != SfxObjectCreateMode::ORGANIZER) |
657 | 0 | bRet = aImport.Export(false); |
658 | 0 | else |
659 | 0 | bRet = aImport.Export(true); |
660 | |
|
661 | 0 | m_pDocument->EnableIdle(true); |
662 | |
|
663 | 0 | return bRet; |
664 | 0 | } |
665 | | |
666 | | bool ScDocShell::Load( SfxMedium& rMedium ) |
667 | 0 | { |
668 | 0 | LoadMediumGuard aLoadGuard(m_pDocument.get()); |
669 | 0 | ScRefreshTimerProtector aProt( m_pDocument->GetRefreshTimerControlAddress() ); |
670 | | |
671 | | // only the latin script language is loaded |
672 | | // -> initialize the others from options (before loading) |
673 | 0 | InitOptions(true); |
674 | | |
675 | | // If this is an ODF file being loaded, then by default, use legacy processing |
676 | | // (if required, it will be overridden in *::ReadUserDataSequence()) |
677 | 0 | if (IsOwnStorageFormat(rMedium)) |
678 | 0 | { |
679 | 0 | if (ScDrawLayer* pDrawLayer = m_pDocument->GetDrawLayer()) |
680 | 0 | { |
681 | 0 | pDrawLayer->SetCompatibilityFlag(SdrCompatibilityFlag::AnchoredTextOverflowLegacy, |
682 | 0 | true); // for tdf#99729 |
683 | 0 | pDrawLayer->SetCompatibilityFlag(SdrCompatibilityFlag::LegacyFontwork, |
684 | 0 | true); // for tdf#148000 |
685 | 0 | } |
686 | 0 | } |
687 | |
|
688 | 0 | GetUndoManager()->Clear(); |
689 | |
|
690 | 0 | bool bRet = SfxObjectShell::Load(rMedium); |
691 | 0 | if (bRet) |
692 | 0 | { |
693 | 0 | SetInitialLinkUpdate(&rMedium); |
694 | |
|
695 | 0 | { |
696 | | // prepare a valid document for XML filter |
697 | | // (for ConvertFrom, InitNew is called before) |
698 | 0 | m_pDocument->MakeTable(0); |
699 | 0 | m_pDocument->GetStyleSheetPool()->CreateStandardStyles(); |
700 | 0 | m_pDocument->getCellAttributeHelper().UpdateAllStyleSheets(*m_pDocument); |
701 | | |
702 | | /* Create styles that are imported through Orcus */ |
703 | |
|
704 | 0 | OUString aURL(u"$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/calc/styles.xml"_ustr); |
705 | 0 | rtl::Bootstrap::expandMacros(aURL); |
706 | |
|
707 | 0 | OUString aPath; |
708 | 0 | osl::FileBase::getSystemPathFromFileURL(aURL, aPath); |
709 | |
|
710 | 0 | ScOrcusFilters* pOrcus = ScFormatFilter::Get().GetOrcusFilters(); |
711 | |
|
712 | 0 | if (pOrcus) |
713 | 0 | { |
714 | 0 | pOrcus->importODS_Styles(*m_pDocument, aPath); |
715 | 0 | m_pDocument->GetStyleSheetPool()->setAllParaStandard(); |
716 | 0 | } |
717 | |
|
718 | 0 | bRet = LoadXML( &rMedium, nullptr ); |
719 | 0 | } |
720 | 0 | } |
721 | |
|
722 | 0 | if (!bRet && !rMedium.GetErrorIgnoreWarning()) |
723 | 0 | rMedium.SetError(SVSTREAM_FILEFORMAT_ERROR); |
724 | |
|
725 | 0 | if (rMedium.GetErrorIgnoreWarning()) |
726 | 0 | SetError(rMedium.GetErrorIgnoreWarning()); |
727 | |
|
728 | 0 | InitItems(); |
729 | 0 | CalcOutputFactor(); |
730 | | |
731 | | // invalidate eventually temporary table areas |
732 | 0 | if ( bRet ) |
733 | 0 | m_pDocument->InvalidateTableArea(); |
734 | |
|
735 | 0 | m_bIsEmpty = false; |
736 | 0 | FinishedLoading(); |
737 | 0 | return bRet; |
738 | 0 | } |
739 | | |
740 | | void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint ) |
741 | 664k | { |
742 | 664k | if (rHint.GetId() == SfxHintId::ScTables) |
743 | 6.30k | { |
744 | 6.30k | const ScTablesHint* pScHint = static_cast< const ScTablesHint* >( &rHint ); |
745 | 6.30k | if (pScHint->GetTablesHintId() == SC_TAB_INSERTED) |
746 | 6.30k | { |
747 | 6.30k | uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = m_pDocument->GetVbaEventProcessor(); |
748 | 6.30k | if ( xVbaEvents.is() ) try |
749 | 0 | { |
750 | 0 | uno::Sequence< uno::Any > aArgs{ uno::Any(pScHint->GetTab1()) }; |
751 | 0 | xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_NEWSHEET, aArgs ); |
752 | 0 | } |
753 | 0 | catch( uno::Exception& ) |
754 | 0 | { |
755 | 0 | } |
756 | 6.30k | } |
757 | 6.30k | } |
758 | | |
759 | 664k | if ( auto pStyleSheetHint = dynamic_cast<const SfxStyleSheetHint*>(&rHint) ) // Template changed |
760 | 102k | NotifyStyle( *pStyleSheetHint ); |
761 | 562k | else if ( rHint.GetId() == SfxHintId::ScAutoStyle ) |
762 | 0 | { |
763 | 0 | auto pStlHint = static_cast<const ScAutoStyleHint*>(&rHint); |
764 | | //! direct call for AutoStyles |
765 | | |
766 | | // this is called synchronously from ScInterpreter::ScStyle, |
767 | | // modifying the document must be asynchronous |
768 | | // (handled by AddInitial) |
769 | |
|
770 | 0 | const ScRange& aRange = pStlHint->GetRange(); |
771 | 0 | const OUString& aName1 = pStlHint->GetStyle1(); |
772 | 0 | const OUString& aName2 = pStlHint->GetStyle2(); |
773 | 0 | sal_uInt32 nTimeout = pStlHint->GetTimeout(); |
774 | |
|
775 | 0 | if (!m_pAutoStyleList) |
776 | 0 | m_pAutoStyleList.reset( new ScAutoStyleList(this) ); |
777 | 0 | m_pAutoStyleList->AddInitial( aRange, aName1, nTimeout, aName2 ); |
778 | 0 | } |
779 | 562k | else if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint) |
780 | 7.33k | { |
781 | 7.33k | switch (static_cast<const SfxEventHint&>(rHint).GetEventId()) |
782 | 7.33k | { |
783 | 0 | case SfxEventHintId::LoadFinished: |
784 | 0 | { |
785 | | #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT |
786 | | // the readonly documents should not be opened in shared mode |
787 | | if ( HasSharedXMLFlagSet() && !ScModule::get()->IsInSharedDocLoading() && !IsReadOnly() ) |
788 | | { |
789 | | if ( SwitchToShared( true, false ) ) |
790 | | { |
791 | | ScViewData* pViewData = GetViewData(); |
792 | | ScTabView* pTabView = ( pViewData ? pViewData->GetView() : nullptr ); |
793 | | if ( pTabView ) |
794 | | { |
795 | | pTabView->UpdateLayerLocks(); |
796 | | } |
797 | | } |
798 | | else |
799 | | { |
800 | | // switching to shared mode has failed, the document should be opened readonly |
801 | | // TODO/LATER: And error message should be shown here probably |
802 | | SetReadOnlyUI(); |
803 | | } |
804 | | } |
805 | | #endif |
806 | 0 | } |
807 | 0 | break; |
808 | 0 | case SfxEventHintId::ViewCreated: |
809 | 0 | { |
810 | | #if HAVE_FEATURE_SCRIPTING |
811 | | uno::Reference<script::vba::XVBACompatibility> xVBACompat(GetBasicContainer(), uno::UNO_QUERY); |
812 | | if ( !m_xVBAListener.is() && xVBACompat.is() ) |
813 | | { |
814 | | m_xVBAListener.set(new VBAScriptListener(this)); |
815 | | xVBACompat->addVBAScriptListener(m_xVBAListener); |
816 | | } |
817 | | #endif |
818 | |
|
819 | | #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT |
820 | | if (ScModule* mod = ScModule::get(); IsDocShared() && !mod->IsInSharedDocLoading() |
821 | | && !comphelper::LibreOfficeKit::isActive() ) |
822 | | { |
823 | | ScAppOptions aAppOptions = mod->GetAppOptions(); |
824 | | if ( aAppOptions.GetShowSharedDocumentWarning() ) |
825 | | { |
826 | | MessageWithCheck aWarningBox(ScDocShell::GetActiveDialogParent(), |
827 | | u"modules/scalc/ui/sharedwarningdialog.ui"_ustr, u"SharedWarningDialog"_ustr); |
828 | | aWarningBox.run(); |
829 | | |
830 | | bool bChecked = aWarningBox.get_active(); |
831 | | if (bChecked) |
832 | | { |
833 | | aAppOptions.SetShowSharedDocumentWarning(false); |
834 | | mod->SetAppOptions(aAppOptions); |
835 | | } |
836 | | } |
837 | | } |
838 | | #endif |
839 | |
|
840 | 0 | ScViewData* pViewData = GetViewData(); |
841 | 0 | SfxViewShell* pViewShell = pViewData ? pViewData->GetViewShell() : nullptr; |
842 | 0 | SfxViewFrame* pViewFrame = pViewShell ? &pViewShell->GetViewFrame() : nullptr; |
843 | |
|
844 | 0 | try |
845 | 0 | { |
846 | 0 | const uno::Reference< uno::XComponentContext >& xContext( |
847 | 0 | comphelper::getProcessComponentContext() ); |
848 | 0 | uno::Reference< lang::XMultiServiceFactory > xServiceManager( |
849 | 0 | xContext->getServiceManager(), |
850 | 0 | uno::UNO_QUERY_THROW ); |
851 | 0 | uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xServiceManager, uno::UNO_QUERY_THROW ); |
852 | 0 | uno::Reference< container::XEnumeration> xEnum = xEnumAccess->createContentEnumeration( |
853 | 0 | u"com.sun.star.sheet.SpreadsheetDocumentJob"_ustr ); |
854 | 0 | if ( xEnum.is() ) |
855 | 0 | { |
856 | 0 | while ( xEnum->hasMoreElements() ) |
857 | 0 | { |
858 | 0 | uno::Any aAny = xEnum->nextElement(); |
859 | 0 | uno::Reference< lang::XSingleComponentFactory > xFactory; |
860 | 0 | aAny >>= xFactory; |
861 | 0 | if ( xFactory.is() ) |
862 | 0 | { |
863 | 0 | uno::Reference< task::XJob > xJob( xFactory->createInstanceWithContext( xContext ), uno::UNO_QUERY_THROW ); |
864 | 0 | SfxFrame* pFrame = ( pViewFrame ? &pViewFrame->GetFrame() : nullptr ); |
865 | 0 | uno::Reference< frame::XController > xController = ( pFrame ? pFrame->GetController() : nullptr ); |
866 | 0 | uno::Reference< sheet::XSpreadsheetView > xSpreadsheetView( xController, uno::UNO_QUERY_THROW ); |
867 | 0 | uno::Sequence< beans::NamedValue > aArgsForJob { { u"SpreadsheetView"_ustr, uno::Any( xSpreadsheetView ) } }; |
868 | 0 | xJob->execute( aArgsForJob ); |
869 | 0 | } |
870 | 0 | } |
871 | 0 | } |
872 | 0 | } |
873 | 0 | catch ( uno::Exception & ) |
874 | 0 | { |
875 | 0 | } |
876 | | |
877 | | // Show delayed infobar entries |
878 | 0 | if (pViewFrame) |
879 | 0 | { |
880 | 0 | for (auto const& r : m_pImpl->mpDelayedInfobarEntry) |
881 | 0 | { |
882 | 0 | pViewFrame->AppendInfoBar(r.msId, r.msPrimaryMessage, r.msSecondaryMessage, r.maInfobarType, r.mbShowCloseButton); |
883 | 0 | } |
884 | 0 | m_pImpl->mpDelayedInfobarEntry.clear(); |
885 | 0 | } |
886 | 0 | } |
887 | 0 | break; |
888 | 0 | case SfxEventHintId::SaveDoc: |
889 | 0 | { |
890 | | #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT |
891 | | if (ScModule* mod = ScModule::get(); IsDocShared() && !mod->IsInSharedDocSaving()) |
892 | | { |
893 | | bool bSuccess = false; |
894 | | bool bRetry = true; |
895 | | while ( bRetry ) |
896 | | { |
897 | | bRetry = false; |
898 | | uno::Reference< frame::XModel > xModel; |
899 | | try |
900 | | { |
901 | | // load shared file |
902 | | xModel.set( LoadSharedDocument(), uno::UNO_SET_THROW ); |
903 | | uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY_THROW ); |
904 | | |
905 | | // check if shared flag is set in shared file |
906 | | bool bShared = false; |
907 | | ScModelObj* pDocObj = comphelper::getFromUnoTunnel<ScModelObj>( xModel ); |
908 | | ScDocShell* pSharedDocShell = ( pDocObj ? dynamic_cast< ScDocShell* >( pDocObj->GetObjectShell() ) : nullptr ); |
909 | | if ( pSharedDocShell ) |
910 | | { |
911 | | bShared = pSharedDocShell->HasSharedXMLFlagSet(); |
912 | | } |
913 | | |
914 | | // #i87870# check if shared status was disabled and enabled again |
915 | | bool bOwnEntry = false; |
916 | | bool bEntriesNotAccessible = false; |
917 | | try |
918 | | { |
919 | | ::svt::ShareControlFile aControlFile( GetSharedFileURL() ); |
920 | | bOwnEntry = aControlFile.HasOwnEntry(); |
921 | | } |
922 | | catch ( uno::Exception& ) |
923 | | { |
924 | | bEntriesNotAccessible = true; |
925 | | } |
926 | | |
927 | | if ( bShared && bOwnEntry ) |
928 | | { |
929 | | uno::Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY_THROW ); |
930 | | |
931 | | if ( xStorable->isReadonly() ) |
932 | | { |
933 | | xCloseable->close( true ); |
934 | | |
935 | | OUString aUserName( ScResId( STR_UNKNOWN_USER ) ); |
936 | | bool bNoLockAccess = false; |
937 | | try |
938 | | { |
939 | | ::svt::DocumentLockFile aLockFile( GetSharedFileURL() ); |
940 | | LockFileEntry aData = aLockFile.GetLockData(); |
941 | | if ( !aData[LockFileComponent::OOOUSERNAME].isEmpty() ) |
942 | | { |
943 | | aUserName = aData[LockFileComponent::OOOUSERNAME]; |
944 | | } |
945 | | else if ( !aData[LockFileComponent::SYSUSERNAME].isEmpty() ) |
946 | | { |
947 | | aUserName = aData[LockFileComponent::SYSUSERNAME]; |
948 | | } |
949 | | } |
950 | | catch ( uno::Exception& ) |
951 | | { |
952 | | bNoLockAccess = true; |
953 | | } |
954 | | |
955 | | if ( bNoLockAccess ) |
956 | | { |
957 | | // TODO/LATER: in future an error regarding impossibility to open file for writing could be shown |
958 | | ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); |
959 | | } |
960 | | else |
961 | | { |
962 | | OUString aMessage( ScResId( STR_FILE_LOCKED_SAVE_LATER ) ); |
963 | | aMessage = aMessage.replaceFirst( "%1", aUserName ); |
964 | | |
965 | | std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetActiveDialogParent(), |
966 | | VclMessageType::Warning, VclButtonsType::NONE, |
967 | | aMessage)); |
968 | | xWarn->add_button(GetStandardText(StandardButtonType::Retry), RET_RETRY); |
969 | | xWarn->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL); |
970 | | xWarn->set_default_response(RET_RETRY); |
971 | | if (xWarn->run() == RET_RETRY) |
972 | | { |
973 | | bRetry = true; |
974 | | } |
975 | | } |
976 | | } |
977 | | else |
978 | | { |
979 | | // merge changes from shared file into temp file |
980 | | bool bSaveToShared = false; |
981 | | if ( pSharedDocShell ) |
982 | | { |
983 | | bSaveToShared = MergeSharedDocument( pSharedDocShell ); |
984 | | } |
985 | | |
986 | | // close shared file |
987 | | xCloseable->close( true ); |
988 | | |
989 | | // TODO: keep file lock on shared file |
990 | | |
991 | | // store to shared file |
992 | | if ( bSaveToShared ) |
993 | | { |
994 | | bool bChangedViewSettings = false; |
995 | | ScChangeViewSettings* pChangeViewSet = m_pDocument->GetChangeViewSettings(); |
996 | | if ( pChangeViewSet && pChangeViewSet->ShowChanges() ) |
997 | | { |
998 | | pChangeViewSet->SetShowChanges( false ); |
999 | | pChangeViewSet->SetShowAccepted( false ); |
1000 | | m_pDocument->SetChangeViewSettings( *pChangeViewSet ); |
1001 | | bChangedViewSettings = true; |
1002 | | } |
1003 | | |
1004 | | // TODO/LATER: More entries from the MediaDescriptor might be interesting for the merge |
1005 | | uno::Sequence< beans::PropertyValue > aValues{ |
1006 | | comphelper::makePropertyValue( |
1007 | | u"FilterName"_ustr, |
1008 | | GetMedium()->GetFilter()->GetFilterName()) |
1009 | | }; |
1010 | | |
1011 | | const SfxStringItem* pPasswordItem = GetMedium()->GetItemSet().GetItem(SID_PASSWORD, false); |
1012 | | if ( pPasswordItem && !pPasswordItem->GetValue().isEmpty() ) |
1013 | | { |
1014 | | aValues.realloc( 2 ); |
1015 | | auto pValues = aValues.getArray(); |
1016 | | pValues[1].Name = "Password"; |
1017 | | pValues[1].Value <<= pPasswordItem->GetValue(); |
1018 | | } |
1019 | | const SfxUnoAnyItem* pEncryptionItem = GetMedium()->GetItemSet().GetItem(SID_ENCRYPTIONDATA, false); |
1020 | | if (pEncryptionItem) |
1021 | | { |
1022 | | aValues.realloc(aValues.getLength() + 1); |
1023 | | auto pValues = aValues.getArray(); |
1024 | | pValues[aValues.getLength() - 1].Name = "EncryptionData"; |
1025 | | pValues[aValues.getLength() - 1].Value = pEncryptionItem->GetValue(); |
1026 | | } |
1027 | | |
1028 | | mod->SetInSharedDocSaving(true); |
1029 | | GetModel()->storeToURL( GetSharedFileURL(), aValues ); |
1030 | | mod->SetInSharedDocSaving(false); |
1031 | | |
1032 | | if ( bChangedViewSettings ) |
1033 | | { |
1034 | | pChangeViewSet->SetShowChanges( true ); |
1035 | | pChangeViewSet->SetShowAccepted( true ); |
1036 | | m_pDocument->SetChangeViewSettings( *pChangeViewSet ); |
1037 | | } |
1038 | | } |
1039 | | |
1040 | | bSuccess = true; |
1041 | | GetUndoManager()->Clear(); |
1042 | | } |
1043 | | } |
1044 | | else |
1045 | | { |
1046 | | xCloseable->close( true ); |
1047 | | |
1048 | | if ( bEntriesNotAccessible ) |
1049 | | { |
1050 | | // TODO/LATER: in future an error regarding impossibility to write to share control file could be shown |
1051 | | ErrorHandler::HandleError( ERRCODE_IO_GENERAL ); |
1052 | | } |
1053 | | else |
1054 | | { |
1055 | | std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetActiveDialogParent(), |
1056 | | VclMessageType::Warning, VclButtonsType::Ok, |
1057 | | ScResId(STR_DOC_NOLONGERSHARED))); |
1058 | | xWarn->run(); |
1059 | | |
1060 | | SfxBindings* pBindings = GetViewBindings(); |
1061 | | if ( pBindings ) |
1062 | | { |
1063 | | pBindings->ExecuteSynchron( SID_SAVEASDOC ); |
1064 | | } |
1065 | | } |
1066 | | } |
1067 | | } |
1068 | | catch ( uno::Exception& ) |
1069 | | { |
1070 | | TOOLS_WARN_EXCEPTION( "sc", "SfxEventHintId::SaveDoc" ); |
1071 | | mod->SetInSharedDocSaving(false); |
1072 | | |
1073 | | try |
1074 | | { |
1075 | | uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW ); |
1076 | | xClose->close( true ); |
1077 | | } |
1078 | | catch ( uno::Exception& ) |
1079 | | { |
1080 | | } |
1081 | | } |
1082 | | } |
1083 | | |
1084 | | if ( !bSuccess ) |
1085 | | SetError(ERRCODE_IO_ABORT); // this error code will produce no error message, but will break the further saving process |
1086 | | } |
1087 | | #endif |
1088 | |
|
1089 | 0 | if (m_pSheetSaveData) |
1090 | 0 | m_pSheetSaveData->SetInSupportedSave(true); |
1091 | 0 | } |
1092 | 0 | break; |
1093 | 0 | case SfxEventHintId::SaveAsDoc: |
1094 | 0 | { |
1095 | 0 | if ( GetDocument().GetExternalRefManager()->containsUnsavedReferences() ) |
1096 | 0 | { |
1097 | 0 | std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetActiveDialogParent(), |
1098 | 0 | VclMessageType::Warning, VclButtonsType::YesNo, |
1099 | 0 | ScResId(STR_UNSAVED_EXT_REF))); |
1100 | 0 | if (RET_NO == xWarn->run()) |
1101 | 0 | { |
1102 | 0 | SetError(ERRCODE_IO_ABORT); // this error code will produce no error message, but will break the further saving process |
1103 | 0 | } |
1104 | 0 | } |
1105 | 0 | [[fallthrough]]; |
1106 | 0 | } |
1107 | 0 | case SfxEventHintId::SaveToDoc: |
1108 | | // #i108978# If no event is sent before saving, there will also be no "...DONE" event, |
1109 | | // and SAVE/SAVEAS can't be distinguished from SAVETO. So stream copying is only enabled |
1110 | | // if there is a SAVE/SAVEAS/SAVETO event first. |
1111 | 0 | if (m_pSheetSaveData) |
1112 | 0 | m_pSheetSaveData->SetInSupportedSave(true); |
1113 | 0 | break; |
1114 | 0 | case SfxEventHintId::SaveDocDone: |
1115 | 0 | case SfxEventHintId::SaveAsDocDone: |
1116 | 0 | { |
1117 | | // new positions are used after "save" and "save as", but not "save to" |
1118 | 0 | UseSheetSaveEntries(); // use positions from saved file for next saving |
1119 | 0 | [[fallthrough]]; |
1120 | 0 | } |
1121 | 0 | case SfxEventHintId::SaveToDocDone: |
1122 | | // only reset the flag, don't use the new positions |
1123 | 0 | if (m_pSheetSaveData) |
1124 | 0 | m_pSheetSaveData->SetInSupportedSave(false); |
1125 | 0 | break; |
1126 | 7.33k | default: |
1127 | 7.33k | { |
1128 | 7.33k | } |
1129 | 7.33k | break; |
1130 | 7.33k | } |
1131 | 7.33k | } |
1132 | 554k | else if (rHint.GetId() == SfxHintId::TitleChanged) // Without parameter |
1133 | 77.1k | { |
1134 | 77.1k | m_pDocument->SetName( SfxShell::GetName() ); |
1135 | | // RegisterNewTargetNames doesn't exist any longer |
1136 | 77.1k | SfxGetpApp()->Broadcast(SfxHint( SfxHintId::ScDocNameChanged )); // Navigator |
1137 | 77.1k | } |
1138 | 477k | else if (rHint.GetId() == SfxHintId::Deinitializing) |
1139 | 77.1k | { |
1140 | | |
1141 | | #if HAVE_FEATURE_SCRIPTING |
1142 | | uno::Reference<script::vba::XVBACompatibility> xVBACompat(GetBasicContainer(), uno::UNO_QUERY); |
1143 | | if (m_xVBAListener.is() && xVBACompat.is()) |
1144 | | { |
1145 | | xVBACompat->removeVBAScriptListener(m_xVBAListener); |
1146 | | } |
1147 | | #endif |
1148 | | |
1149 | 77.1k | if (m_pDocument->IsClipboardSource()) |
1150 | 0 | { |
1151 | | // Notes copied to the clipboard have a raw SdrCaptionObj pointer |
1152 | | // copied from this document, forget it as it references this |
1153 | | // document's drawing layer pages and what not, which otherwise when |
1154 | | // pasting to another document after this document was destructed would |
1155 | | // attempt to access non-existing data. Preserve the text data though. |
1156 | 0 | ScDocument* pClipDoc = ScModule::GetClipDoc(); |
1157 | 0 | if (pClipDoc) |
1158 | 0 | pClipDoc->ClosingClipboardSource(); |
1159 | 0 | } |
1160 | 77.1k | } |
1161 | | |
1162 | 664k | if (rHint.GetId() != SfxHintId::ThisIsAnSfxEventHint) |
1163 | 657k | return; |
1164 | | |
1165 | 7.33k | switch(static_cast<const SfxEventHint&>(rHint).GetEventId()) |
1166 | 7.33k | { |
1167 | 0 | case SfxEventHintId::CreateDoc: |
1168 | 0 | { |
1169 | 0 | uno::Any aWorkbook; |
1170 | 0 | aWorkbook <<= mxAutomationWorkbookObject; |
1171 | 0 | uno::Sequence< uno::Any > aArgs{ aWorkbook }; |
1172 | 0 | ScModule::get()->CallAutomationApplicationEventSinks(u"NewWorkbook"_ustr, aArgs); |
1173 | 0 | } |
1174 | 0 | break; |
1175 | 0 | case SfxEventHintId::OpenDoc: |
1176 | 0 | { |
1177 | 0 | uno::Any aWorkbook; |
1178 | 0 | aWorkbook <<= mxAutomationWorkbookObject; |
1179 | 0 | uno::Sequence< uno::Any > aArgs{ aWorkbook }; |
1180 | 0 | ScModule::get()->CallAutomationApplicationEventSinks(u"WorkbookOpen"_ustr, aArgs); |
1181 | 0 | } |
1182 | 0 | break; |
1183 | 7.33k | default: |
1184 | 7.33k | break; |
1185 | 7.33k | } |
1186 | 7.33k | } |
1187 | | |
1188 | | // Load contents for organizer |
1189 | | bool ScDocShell::LoadFrom( SfxMedium& rMedium ) |
1190 | 0 | { |
1191 | 0 | LoadMediumGuard aLoadGuard(m_pDocument.get()); |
1192 | 0 | ScRefreshTimerProtector aProt( m_pDocument->GetRefreshTimerControlAddress() ); |
1193 | |
|
1194 | 0 | weld::WaitObject aWait( GetActiveDialogParent() ); |
1195 | |
|
1196 | 0 | bool bRet = false; |
1197 | |
|
1198 | 0 | SetInitialLinkUpdate(&rMedium); |
1199 | | |
1200 | | // until loading/saving only the styles in XML is implemented, |
1201 | | // load the whole file |
1202 | 0 | bRet = LoadXML( &rMedium, nullptr ); |
1203 | 0 | InitItems(); |
1204 | |
|
1205 | 0 | SfxObjectShell::LoadFrom( rMedium ); |
1206 | |
|
1207 | 0 | return bRet; |
1208 | 0 | } |
1209 | | |
1210 | | static void lcl_parseHtmlFilterOption(const OUString& rOption, LanguageType& rLang, bool& rDateConvert, bool& rScientificConvert) |
1211 | 0 | { |
1212 | 0 | OUStringBuffer aBuf; |
1213 | 0 | std::vector< OUString > aTokens; |
1214 | 0 | sal_Int32 n = rOption.getLength(); |
1215 | 0 | const sal_Unicode* p = rOption.getStr(); |
1216 | 0 | for (sal_Int32 i = 0; i < n; ++i) |
1217 | 0 | { |
1218 | 0 | const sal_Unicode c = p[i]; |
1219 | 0 | if (c == ' ') |
1220 | 0 | { |
1221 | 0 | if (!aBuf.isEmpty()) |
1222 | 0 | aTokens.push_back( aBuf.makeStringAndClear() ); |
1223 | 0 | } |
1224 | 0 | else |
1225 | 0 | aBuf.append(c); |
1226 | 0 | } |
1227 | |
|
1228 | 0 | if (!aBuf.isEmpty()) |
1229 | 0 | aTokens.push_back( aBuf.makeStringAndClear() ); |
1230 | |
|
1231 | 0 | rLang = LanguageType( 0 ); |
1232 | 0 | rDateConvert = false; |
1233 | |
|
1234 | 0 | if (!aTokens.empty()) |
1235 | 0 | rLang = static_cast<LanguageType>(aTokens[0].toInt32()); |
1236 | 0 | if (aTokens.size() > 1) |
1237 | 0 | rDateConvert = static_cast<bool>(aTokens[1].toInt32()); |
1238 | 0 | if (aTokens.size() > 2) |
1239 | 0 | rScientificConvert = static_cast<bool>(aTokens[2].toInt32()); |
1240 | 0 | } |
1241 | | |
1242 | | bool ScDocShell::ConvertFrom( SfxMedium& rMedium ) |
1243 | 0 | { |
1244 | 0 | LoadMediumGuard aLoadGuard(m_pDocument.get()); |
1245 | |
|
1246 | 0 | bool bRet = false; // sal_False means user quit! |
1247 | | // On error: Set error at stream |
1248 | |
|
1249 | 0 | ScRefreshTimerProtector aProt( m_pDocument->GetRefreshTimerControlAddress() ); |
1250 | |
|
1251 | 0 | GetUndoManager()->Clear(); |
1252 | | |
1253 | | // Set optimal col width after import? |
1254 | 0 | bool bSetColWidths = false; |
1255 | 0 | bool bSetSimpleTextColWidths = false; |
1256 | 0 | std::map<SCCOL, ScColWidthParam> aColWidthParam; |
1257 | 0 | ScRange aColWidthRange; |
1258 | | // Set optimal row height after import? |
1259 | 0 | bool bSetRowHeights = false; |
1260 | |
|
1261 | 0 | vector<ScDocRowHeightUpdater::TabRanges> aRecalcRowRangesArray; |
1262 | | |
1263 | | // All filters need the complete file in one piece (not asynchronously) |
1264 | | // So make sure that we transfer the whole file with CreateFileStream |
1265 | 0 | rMedium.GetPhysicalName(); //! Call CreateFileStream directly, if available |
1266 | |
|
1267 | 0 | SetInitialLinkUpdate(&rMedium); |
1268 | |
|
1269 | 0 | std::shared_ptr<const SfxFilter> pFilter = rMedium.GetFilter(); |
1270 | 0 | if (pFilter) |
1271 | 0 | { |
1272 | 0 | OUString aFltName = pFilter->GetFilterName(); |
1273 | |
|
1274 | 0 | bool bCalc3 = aFltName == "StarCalc 3.0"; |
1275 | 0 | bool bCalc4 = aFltName == "StarCalc 4.0"; |
1276 | 0 | if (!bCalc3 && !bCalc4) |
1277 | 0 | m_pDocument->SetInsertingFromOtherDoc( true ); |
1278 | |
|
1279 | 0 | if (aFltName == pFilterXML) |
1280 | 0 | bRet = LoadXML( &rMedium, nullptr ); |
1281 | 0 | else if (aFltName == pFilterLotus) |
1282 | 0 | { |
1283 | 0 | OUString sItStr; |
1284 | 0 | if ( const SfxStringItem* pOptionsItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS, true ) ) |
1285 | 0 | { |
1286 | 0 | sItStr = pOptionsItem->GetValue(); |
1287 | 0 | } |
1288 | |
|
1289 | 0 | if (sItStr.isEmpty()) |
1290 | 0 | { |
1291 | | // default for lotus import (from API without options): |
1292 | | // IBM_437 encoding |
1293 | 0 | sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_437 ); |
1294 | 0 | } |
1295 | |
|
1296 | 0 | ErrCode eError = ScFormatFilter::Get().ScImportLotus123( rMedium, *m_pDocument, |
1297 | 0 | ScGlobal::GetCharsetValue(sItStr)); |
1298 | 0 | if (eError != ERRCODE_NONE) |
1299 | 0 | { |
1300 | 0 | if (!GetErrorIgnoreWarning()) |
1301 | 0 | SetError(eError); |
1302 | |
|
1303 | 0 | if( eError.IsWarning() ) |
1304 | 0 | bRet = true; |
1305 | 0 | } |
1306 | 0 | else |
1307 | 0 | bRet = true; |
1308 | 0 | bSetColWidths = true; |
1309 | 0 | bSetRowHeights = true; |
1310 | 0 | } |
1311 | 0 | else if ( aFltName == pFilterExcel4 || aFltName == pFilterExcel5 || |
1312 | 0 | aFltName == pFilterExcel95 || aFltName == pFilterExcel97 || |
1313 | 0 | aFltName == pFilterEx4Temp || aFltName == pFilterEx5Temp || |
1314 | 0 | aFltName == pFilterEx95Temp || aFltName == pFilterEx97Temp ) |
1315 | 0 | { |
1316 | 0 | EXCIMPFORMAT eFormat = EIF_AUTO; |
1317 | 0 | if ( aFltName == pFilterExcel4 || aFltName == pFilterEx4Temp ) |
1318 | 0 | eFormat = EIF_BIFF_LE4; |
1319 | 0 | else if ( aFltName == pFilterExcel5 || aFltName == pFilterExcel95 || |
1320 | 0 | aFltName == pFilterEx5Temp || aFltName == pFilterEx95Temp ) |
1321 | 0 | eFormat = EIF_BIFF5; |
1322 | 0 | else if ( aFltName == pFilterExcel97 || aFltName == pFilterEx97Temp ) |
1323 | 0 | eFormat = EIF_BIFF8; |
1324 | |
|
1325 | 0 | MakeDrawLayer(); //! In the filter |
1326 | 0 | CalcOutputFactor(); // prepare update of row height |
1327 | 0 | ErrCode eError = ScFormatFilter::Get().ScImportExcel( rMedium, m_pDocument.get(), eFormat ); |
1328 | 0 | m_pDocument->UpdateFontCharSet(); |
1329 | 0 | if ( m_pDocument->IsChartListenerCollectionNeedsUpdate() ) |
1330 | 0 | m_pDocument->UpdateChartListenerCollection(); //! For all imports? |
1331 | | |
1332 | | // all graphics objects must have names |
1333 | 0 | m_pDocument->EnsureGraphicNames(); |
1334 | |
|
1335 | 0 | if (eError == SCWARN_IMPORT_UNKNOWN_ENCRYPTION) |
1336 | 0 | { |
1337 | |
|
1338 | 0 | m_pImpl->mpDelayedInfobarEntry.push_back({ u"UnknownEncryption"_ustr, ScResId(STR_CONTENT_WITH_UNKNOWN_ENCRYPTION), u""_ustr, InfobarType::INFO, true }); |
1339 | 0 | eError = ERRCODE_NONE; |
1340 | 0 | } |
1341 | |
|
1342 | 0 | if (eError != ERRCODE_NONE) |
1343 | 0 | { |
1344 | 0 | if (!GetErrorIgnoreWarning()) |
1345 | 0 | SetError(eError); |
1346 | 0 | if( eError.IsWarning() ) |
1347 | 0 | bRet = true; |
1348 | 0 | } |
1349 | 0 | else |
1350 | 0 | bRet = true; |
1351 | 0 | } |
1352 | 0 | else if (aFltName == SC_TEXT_CSV_FILTER_NAME) |
1353 | 0 | { |
1354 | 0 | ScAsciiOptions aOptions; |
1355 | 0 | bool bOptInit = false; |
1356 | |
|
1357 | 0 | if ( const SfxStringItem* pOptionsItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) |
1358 | 0 | { |
1359 | 0 | aOptions.ReadFromString( pOptionsItem->GetValue(), rMedium.GetInStream() ); |
1360 | 0 | bOptInit = true; |
1361 | 0 | } |
1362 | |
|
1363 | 0 | if ( !bOptInit ) |
1364 | 0 | { |
1365 | | // default for ascii import (from API without options): |
1366 | | // UTF-8 encoding, comma, double quotes |
1367 | |
|
1368 | 0 | aOptions.SetCharSet(RTL_TEXTENCODING_UTF8); |
1369 | 0 | aOptions.SetFieldSeps( OUString(',') ); |
1370 | 0 | aOptions.SetTextSep( '"' ); |
1371 | 0 | } |
1372 | |
|
1373 | 0 | ErrCode eError = ERRCODE_NONE; |
1374 | 0 | bool bOverflowRow, bOverflowCol, bOverflowCell; |
1375 | 0 | bOverflowRow = bOverflowCol = bOverflowCell = false; |
1376 | |
|
1377 | 0 | if( ! rMedium.IsStorage() ) |
1378 | 0 | { |
1379 | 0 | ScImportExport aImpEx( *m_pDocument ); |
1380 | 0 | aImpEx.SetExtOptions( aOptions ); |
1381 | |
|
1382 | 0 | SvStream* pInStream = rMedium.GetInStream(); |
1383 | 0 | if (pInStream) |
1384 | 0 | { |
1385 | 0 | pInStream->SetStreamCharSet( aOptions.GetCharSet() ); |
1386 | 0 | pInStream->Seek( 0 ); |
1387 | 0 | bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL(), SotClipboardFormatId::STRING ); |
1388 | 0 | eError = bRet ? ERRCODE_NONE : SCERR_IMPORT_CONNECT; |
1389 | 0 | m_pDocument->StartAllListeners(); |
1390 | 0 | sc::SetFormulaDirtyContext aCxt; |
1391 | 0 | m_pDocument->SetAllFormulasDirty(aCxt); |
1392 | | |
1393 | | // tdf#82254 - check whether to include a byte-order-mark in the output |
1394 | 0 | if (const bool bIncludeBOM = aImpEx.GetIncludeBOM()) |
1395 | 0 | { |
1396 | 0 | aOptions.SetIncludeBOM(bIncludeBOM); |
1397 | 0 | rMedium.GetItemSet().Put( |
1398 | 0 | SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions.WriteToString())); |
1399 | 0 | } |
1400 | | |
1401 | | // for mobile case, we use a copy of the original document and give it a temporary name before editing |
1402 | | // Therefore, the sheet name becomes ugly, long and nonsensical. |
1403 | 0 | #if !(defined ANDROID) |
1404 | | // The same resulting name has to be handled in |
1405 | | // ScExternalRefCache::initializeDoc() and related, hence |
1406 | | // pass 'true' for RenameTab()'s bExternalDocument for a |
1407 | | // composed name so ValidTabName() will not be checked, |
1408 | | // which could veto the rename in case it contained |
1409 | | // characters that Excel does not handle. If we wanted to |
1410 | | // change that then it needed to be handled in all |
1411 | | // corresponding places of the external references |
1412 | | // manager/cache. Likely then we'd also need a method to |
1413 | | // compose a name excluding such characters. |
1414 | 0 | m_pDocument->RenameTab( 0, INetURLObject( rMedium.GetName()).GetBase(), true/*bExternalDocument*/); |
1415 | 0 | #endif |
1416 | 0 | bOverflowRow = aImpEx.IsOverflowRow(); |
1417 | 0 | bOverflowCol = aImpEx.IsOverflowCol(); |
1418 | 0 | bOverflowCell = aImpEx.IsOverflowCell(); |
1419 | 0 | } |
1420 | 0 | else |
1421 | 0 | { |
1422 | 0 | OSL_FAIL( "No Stream" ); |
1423 | 0 | } |
1424 | 0 | } |
1425 | |
|
1426 | 0 | if (eError != ERRCODE_NONE) |
1427 | 0 | { |
1428 | 0 | if (!GetErrorIgnoreWarning()) |
1429 | 0 | SetError(eError); |
1430 | 0 | if( eError.IsWarning() ) |
1431 | 0 | bRet = true; |
1432 | 0 | } |
1433 | 0 | else if (!GetErrorIgnoreWarning() && (bOverflowRow || bOverflowCol || bOverflowCell)) |
1434 | 0 | { |
1435 | | // precedence: row, column, cell |
1436 | 0 | ErrCode nWarn = (bOverflowRow ? SCWARN_IMPORT_ROW_OVERFLOW : |
1437 | 0 | (bOverflowCol ? SCWARN_IMPORT_COLUMN_OVERFLOW : |
1438 | 0 | SCWARN_IMPORT_CELL_OVERFLOW)); |
1439 | 0 | SetError(nWarn); |
1440 | 0 | } |
1441 | 0 | bSetColWidths = true; |
1442 | 0 | bSetSimpleTextColWidths = true; |
1443 | 0 | } |
1444 | 0 | else if (aFltName == pFilterDBase) |
1445 | 0 | { |
1446 | 0 | OUString sItStr; |
1447 | 0 | if ( const SfxStringItem* pOptionsItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) |
1448 | 0 | { |
1449 | 0 | sItStr = pOptionsItem->GetValue(); |
1450 | 0 | } |
1451 | |
|
1452 | 0 | if (sItStr.isEmpty()) |
1453 | 0 | { |
1454 | | // default for dBase import (from API without options): |
1455 | | // IBM_850 encoding |
1456 | |
|
1457 | 0 | sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 ); |
1458 | 0 | } |
1459 | |
|
1460 | 0 | ScDocRowHeightUpdater::TabRanges aRecalcRanges(0, m_pDocument->MaxRow()); |
1461 | 0 | ErrCode eError = DBaseImport( rMedium.GetPhysicalName(), |
1462 | 0 | ScGlobal::GetCharsetValue(sItStr), aColWidthParam, aRecalcRanges.maRanges ); |
1463 | 0 | aRecalcRowRangesArray.push_back(aRecalcRanges); |
1464 | |
|
1465 | 0 | if (eError != ERRCODE_NONE) |
1466 | 0 | { |
1467 | 0 | if (!GetErrorIgnoreWarning()) |
1468 | 0 | SetError(eError); |
1469 | 0 | if( eError.IsWarning() ) |
1470 | 0 | bRet = true; |
1471 | 0 | } |
1472 | 0 | else |
1473 | 0 | bRet = true; |
1474 | |
|
1475 | 0 | aColWidthRange.aStart.SetRow( 1 ); // Except for the column header |
1476 | 0 | bSetColWidths = true; |
1477 | 0 | bSetSimpleTextColWidths = true; |
1478 | 0 | } |
1479 | 0 | else if (aFltName == pFilterDif) |
1480 | 0 | { |
1481 | 0 | SvStream* pStream = rMedium.GetInStream(); |
1482 | 0 | if (pStream) |
1483 | 0 | { |
1484 | 0 | ErrCode eError; |
1485 | 0 | OUString sItStr; |
1486 | 0 | if ( const SfxStringItem* pOptionsItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) |
1487 | 0 | { |
1488 | 0 | sItStr = pOptionsItem->GetValue(); |
1489 | 0 | } |
1490 | |
|
1491 | 0 | if (sItStr.isEmpty()) |
1492 | 0 | { |
1493 | | // default for DIF import (from API without options): |
1494 | | // ISO8859-1/MS_1252 encoding |
1495 | |
|
1496 | 0 | sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 ); |
1497 | 0 | } |
1498 | |
|
1499 | 0 | eError = ScFormatFilter::Get().ScImportDif( *pStream, m_pDocument.get(), ScAddress(0,0,0), |
1500 | 0 | ScGlobal::GetCharsetValue(sItStr)); |
1501 | 0 | if (eError != ERRCODE_NONE) |
1502 | 0 | { |
1503 | 0 | if (!GetErrorIgnoreWarning()) |
1504 | 0 | SetError(eError); |
1505 | |
|
1506 | 0 | if( eError.IsWarning() ) |
1507 | 0 | bRet = true; |
1508 | 0 | } |
1509 | 0 | else |
1510 | 0 | bRet = true; |
1511 | 0 | } |
1512 | 0 | bSetColWidths = true; |
1513 | 0 | bSetSimpleTextColWidths = true; |
1514 | 0 | bSetRowHeights = true; |
1515 | 0 | } |
1516 | 0 | else if (aFltName == pFilterSylk) |
1517 | 0 | { |
1518 | 0 | ErrCode eError = SCERR_IMPORT_UNKNOWN; |
1519 | 0 | bool bOverflowRow, bOverflowCol, bOverflowCell; |
1520 | 0 | bOverflowRow = bOverflowCol = bOverflowCell = false; |
1521 | 0 | if( !rMedium.IsStorage() ) |
1522 | 0 | { |
1523 | 0 | ScImportExport aImpEx( *m_pDocument ); |
1524 | |
|
1525 | 0 | SvStream* pInStream = rMedium.GetInStream(); |
1526 | 0 | if (pInStream) |
1527 | 0 | { |
1528 | 0 | pInStream->Seek( 0 ); |
1529 | 0 | bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL(), SotClipboardFormatId::SYLK ); |
1530 | 0 | eError = bRet ? ERRCODE_NONE : SCERR_IMPORT_UNKNOWN; |
1531 | 0 | m_pDocument->StartAllListeners(); |
1532 | 0 | sc::SetFormulaDirtyContext aCxt; |
1533 | 0 | m_pDocument->SetAllFormulasDirty(aCxt); |
1534 | |
|
1535 | 0 | bOverflowRow = aImpEx.IsOverflowRow(); |
1536 | 0 | bOverflowCol = aImpEx.IsOverflowCol(); |
1537 | 0 | bOverflowCell = aImpEx.IsOverflowCell(); |
1538 | 0 | } |
1539 | 0 | else |
1540 | 0 | { |
1541 | 0 | OSL_FAIL( "No Stream" ); |
1542 | 0 | } |
1543 | 0 | } |
1544 | |
|
1545 | 0 | if (eError != ERRCODE_NONE) |
1546 | 0 | { |
1547 | 0 | if (!GetErrorIgnoreWarning()) |
1548 | 0 | SetError(eError); |
1549 | 0 | if( eError.IsWarning() ) |
1550 | 0 | bRet = true; |
1551 | 0 | } |
1552 | 0 | else if (!GetErrorIgnoreWarning() && (bOverflowRow || bOverflowCol || bOverflowCell)) |
1553 | 0 | { |
1554 | | // precedence: row, column, cell |
1555 | 0 | ErrCode nWarn = (bOverflowRow ? SCWARN_IMPORT_ROW_OVERFLOW : |
1556 | 0 | (bOverflowCol ? SCWARN_IMPORT_COLUMN_OVERFLOW : |
1557 | 0 | SCWARN_IMPORT_CELL_OVERFLOW)); |
1558 | 0 | SetError(nWarn); |
1559 | 0 | } |
1560 | 0 | bSetColWidths = true; |
1561 | 0 | bSetSimpleTextColWidths = true; |
1562 | 0 | bSetRowHeights = true; |
1563 | 0 | } |
1564 | 0 | else if (aFltName == pFilterQPro6) |
1565 | 0 | { |
1566 | 0 | ErrCode eError = ScFormatFilter::Get().ScImportQuattroPro(rMedium.GetInStream(), *m_pDocument); |
1567 | 0 | if (eError != ERRCODE_NONE) |
1568 | 0 | { |
1569 | 0 | if (!GetErrorIgnoreWarning()) |
1570 | 0 | SetError(eError); |
1571 | 0 | if( eError.IsWarning() ) |
1572 | 0 | bRet = true; |
1573 | 0 | } |
1574 | 0 | else |
1575 | 0 | bRet = true; |
1576 | | // TODO: Filter should set column widths. Not doing it here, it may |
1577 | | // result in very narrow or wide columns, depending on content. |
1578 | | // Setting row heights makes cells with font size attribution or |
1579 | | // wrapping enabled look nicer... |
1580 | 0 | bSetRowHeights = true; |
1581 | 0 | } |
1582 | 0 | else if (aFltName == pFilterRtf) |
1583 | 0 | { |
1584 | 0 | ErrCode eError = SCERR_IMPORT_UNKNOWN; |
1585 | 0 | if( !rMedium.IsStorage() ) |
1586 | 0 | { |
1587 | 0 | SvStream* pInStream = rMedium.GetInStream(); |
1588 | 0 | if (pInStream) |
1589 | 0 | { |
1590 | 0 | pInStream->Seek( 0 ); |
1591 | 0 | ScRange aRange; |
1592 | 0 | eError = ScFormatFilter::Get().ScImportRTF( *pInStream, rMedium.GetBaseURL(), *m_pDocument, aRange ); |
1593 | 0 | if (eError != ERRCODE_NONE) |
1594 | 0 | { |
1595 | 0 | if (!GetErrorIgnoreWarning()) |
1596 | 0 | SetError(eError); |
1597 | |
|
1598 | 0 | if( eError.IsWarning() ) |
1599 | 0 | bRet = true; |
1600 | 0 | } |
1601 | 0 | else |
1602 | 0 | bRet = true; |
1603 | 0 | m_pDocument->StartAllListeners(); |
1604 | 0 | sc::SetFormulaDirtyContext aCxt; |
1605 | 0 | m_pDocument->SetAllFormulasDirty(aCxt); |
1606 | 0 | bSetColWidths = true; |
1607 | 0 | bSetRowHeights = true; |
1608 | 0 | } |
1609 | 0 | else |
1610 | 0 | { |
1611 | 0 | OSL_FAIL( "No Stream" ); |
1612 | 0 | } |
1613 | 0 | } |
1614 | |
|
1615 | 0 | if (eError != ERRCODE_NONE) |
1616 | 0 | { |
1617 | 0 | if (!GetErrorIgnoreWarning()) |
1618 | 0 | SetError(eError); |
1619 | 0 | if( eError.IsWarning() ) |
1620 | 0 | bRet = true; |
1621 | 0 | } |
1622 | 0 | } |
1623 | 0 | else if (aFltName == pFilterHtml || aFltName == pFilterHtmlWebQ) |
1624 | 0 | { |
1625 | 0 | ErrCode eError = SCERR_IMPORT_UNKNOWN; |
1626 | 0 | bool bWebQuery = aFltName == pFilterHtmlWebQ; |
1627 | 0 | if( !rMedium.IsStorage() ) |
1628 | 0 | { |
1629 | 0 | SvStream* pInStream = rMedium.GetInStream(); |
1630 | 0 | if (pInStream) |
1631 | 0 | { |
1632 | 0 | LanguageType eLang = LANGUAGE_SYSTEM; |
1633 | 0 | bool bDateConvert = false; |
1634 | 0 | bool bScientificConvert = true; |
1635 | 0 | if ( const SfxStringItem* pOptionsItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) |
1636 | 0 | { |
1637 | 0 | OUString aFilterOption = pOptionsItem->GetValue(); |
1638 | 0 | lcl_parseHtmlFilterOption(aFilterOption, eLang, bDateConvert, bScientificConvert); |
1639 | 0 | } |
1640 | |
|
1641 | 0 | pInStream->Seek( 0 ); |
1642 | 0 | ScRange aRange; |
1643 | | // HTML does its own ColWidth/RowHeight |
1644 | 0 | CalcOutputFactor(); |
1645 | 0 | SvNumberFormatter aNumFormatter( comphelper::getProcessComponentContext(), eLang); |
1646 | 0 | eError = ScFormatFilter::Get().ScImportHTML( *pInStream, rMedium.GetBaseURL(), *m_pDocument, aRange, |
1647 | 0 | GetOutputFactor(), !bWebQuery, &aNumFormatter, bDateConvert, bScientificConvert ); |
1648 | 0 | if (eError != ERRCODE_NONE) |
1649 | 0 | { |
1650 | 0 | if (!GetErrorIgnoreWarning()) |
1651 | 0 | SetError(eError); |
1652 | |
|
1653 | 0 | if( eError.IsWarning() ) |
1654 | 0 | bRet = true; |
1655 | 0 | } |
1656 | 0 | else |
1657 | 0 | bRet = true; |
1658 | 0 | m_pDocument->StartAllListeners(); |
1659 | |
|
1660 | 0 | sc::SetFormulaDirtyContext aCxt; |
1661 | 0 | m_pDocument->SetAllFormulasDirty(aCxt); |
1662 | 0 | } |
1663 | 0 | else |
1664 | 0 | { |
1665 | 0 | OSL_FAIL( "No Stream" ); |
1666 | 0 | } |
1667 | 0 | } |
1668 | |
|
1669 | 0 | if (eError != ERRCODE_NONE) |
1670 | 0 | { |
1671 | 0 | if (!GetErrorIgnoreWarning()) |
1672 | 0 | SetError(eError); |
1673 | 0 | if( eError.IsWarning() ) |
1674 | 0 | bRet = true; |
1675 | 0 | } |
1676 | 0 | } |
1677 | 0 | else |
1678 | 0 | { |
1679 | 0 | ScOrcusFilters* pOrcus = ScFormatFilter::Get().GetOrcusFilters(); |
1680 | 0 | if (!pOrcus) |
1681 | 0 | return false; |
1682 | | |
1683 | 0 | switch (pOrcus->importByName(*m_pDocument, rMedium, aFltName)) |
1684 | 0 | { |
1685 | 0 | case ScOrcusFilters::ImportResult::Success: |
1686 | 0 | bRet = true; |
1687 | 0 | break; |
1688 | 0 | case ScOrcusFilters::ImportResult::Failure: |
1689 | 0 | bRet = false; |
1690 | 0 | break; |
1691 | 0 | case ScOrcusFilters::ImportResult::NotSupported: |
1692 | 0 | { |
1693 | 0 | if (!GetErrorIgnoreWarning()) |
1694 | 0 | { |
1695 | 0 | SAL_WARN("sc.filter", "No match for filter '" << aFltName << "' in ConvertFrom"); |
1696 | 0 | SetError(SCERR_IMPORT_NI); |
1697 | 0 | } |
1698 | 0 | break; |
1699 | 0 | } |
1700 | 0 | } |
1701 | 0 | } |
1702 | | |
1703 | 0 | if (!bCalc3) |
1704 | 0 | m_pDocument->SetInsertingFromOtherDoc( false ); |
1705 | 0 | } |
1706 | 0 | else |
1707 | 0 | { |
1708 | 0 | OSL_FAIL("No Filter in ConvertFrom"); |
1709 | 0 | } |
1710 | | |
1711 | 0 | InitItems(); |
1712 | 0 | CalcOutputFactor(); |
1713 | 0 | if ( bRet && (bSetColWidths || bSetRowHeights) ) |
1714 | 0 | { // Adjust column width/row height; base 100% zoom |
1715 | 0 | Fraction aZoom( 1, 1 ); |
1716 | 0 | double nPPTX = ScGlobal::nScreenPPTX * static_cast<double>(aZoom) / GetOutputFactor(); // Factor is printer display ratio |
1717 | 0 | double nPPTY = ScGlobal::nScreenPPTY * static_cast<double>(aZoom); |
1718 | 0 | ScopedVclPtrInstance< VirtualDevice > pVirtDev; |
1719 | | // all sheets (for Excel import) |
1720 | 0 | SCTAB nTabCount = m_pDocument->GetTableCount(); |
1721 | 0 | for (SCTAB nTab=0; nTab<nTabCount; nTab++) |
1722 | 0 | { |
1723 | 0 | SCCOL nEndCol; |
1724 | 0 | SCROW nEndRow; |
1725 | 0 | m_pDocument->GetCellArea( nTab, nEndCol, nEndRow ); |
1726 | 0 | aColWidthRange.aEnd.SetCol( nEndCol ); |
1727 | 0 | aColWidthRange.aEnd.SetRow( nEndRow ); |
1728 | 0 | ScMarkData aMark(m_pDocument->GetSheetLimits()); |
1729 | 0 | aMark.SetMarkArea( aColWidthRange ); |
1730 | 0 | aMark.MarkToMulti(); |
1731 | | |
1732 | | // Order is important: First width, then height |
1733 | 0 | if ( bSetColWidths ) |
1734 | 0 | { |
1735 | 0 | for ( SCCOL nCol=0; nCol <= nEndCol; nCol++ ) |
1736 | 0 | { |
1737 | 0 | if (!bSetSimpleTextColWidths) |
1738 | 0 | aColWidthParam[nCol].mbSimpleText = false; |
1739 | |
|
1740 | 0 | sal_uInt16 nWidth = m_pDocument->GetOptimalColWidth( |
1741 | 0 | nCol, nTab, pVirtDev, nPPTX, nPPTY, aZoom, aZoom, false, &aMark, |
1742 | 0 | &aColWidthParam[nCol] ); |
1743 | 0 | m_pDocument->SetColWidth( nCol, nTab, |
1744 | 0 | nWidth + static_cast<sal_uInt16>(ScGlobal::nLastColWidthExtra) ); |
1745 | 0 | } |
1746 | 0 | } |
1747 | 0 | } |
1748 | |
|
1749 | 0 | if (bSetRowHeights) |
1750 | 0 | { |
1751 | | // Update all rows in all tables. |
1752 | 0 | ScSizeDeviceProvider aProv(*this); |
1753 | 0 | ScDocRowHeightUpdater aUpdater(*m_pDocument, aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), nullptr); |
1754 | 0 | aUpdater.update(); |
1755 | 0 | } |
1756 | 0 | else if (!aRecalcRowRangesArray.empty()) |
1757 | 0 | { |
1758 | | // Update only specified row ranges for better performance. |
1759 | 0 | ScSizeDeviceProvider aProv(*this); |
1760 | 0 | ScDocRowHeightUpdater aUpdater(*m_pDocument, aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), &aRecalcRowRangesArray); |
1761 | 0 | aUpdater.update(); |
1762 | 0 | } |
1763 | 0 | } |
1764 | 0 | FinishedLoading(); |
1765 | | |
1766 | | // invalidate eventually temporary table areas |
1767 | 0 | if ( bRet ) |
1768 | 0 | m_pDocument->InvalidateTableArea(); |
1769 | |
|
1770 | 0 | m_bIsEmpty = false; |
1771 | |
|
1772 | 0 | return bRet; |
1773 | 0 | } |
1774 | | |
1775 | | bool ScDocShell::LoadExternal( SfxMedium& rMed ) |
1776 | 0 | { |
1777 | 0 | std::shared_ptr<const SfxFilter> pFilter = rMed.GetFilter(); |
1778 | 0 | if (!pFilter) |
1779 | 0 | return false; |
1780 | | |
1781 | 0 | if (pFilter->GetProviderName() == "orcus") |
1782 | 0 | { |
1783 | 0 | ScOrcusFilters* pOrcus = ScFormatFilter::Get().GetOrcusFilters(); |
1784 | 0 | if (!pOrcus) |
1785 | 0 | return false; |
1786 | | |
1787 | 0 | auto res = pOrcus->importByName(*m_pDocument, rMed, pFilter->GetName()); |
1788 | 0 | if (res != ScOrcusFilters::ImportResult::Success) |
1789 | 0 | return false; |
1790 | | |
1791 | 0 | FinishedLoading(); |
1792 | 0 | return true; |
1793 | 0 | } |
1794 | | |
1795 | 0 | return false; |
1796 | 0 | } |
1797 | | |
1798 | | ScDocShell::PrepareSaveGuard::PrepareSaveGuard( ScDocShell& rDocShell ) |
1799 | 0 | : mrDocShell( rDocShell) |
1800 | 0 | { |
1801 | | // DoEnterHandler not here (because of AutoSave), is in ExecuteSave. |
1802 | |
|
1803 | 0 | ScChartListenerCollection* pCharts = mrDocShell.m_pDocument->GetChartListenerCollection(); |
1804 | 0 | if (pCharts) |
1805 | 0 | pCharts->UpdateDirtyCharts(); // Charts to be updated. |
1806 | 0 | mrDocShell.m_pDocument->StopTemporaryChartLock(); |
1807 | 0 | if (mrDocShell.m_pAutoStyleList) |
1808 | 0 | mrDocShell.m_pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now. |
1809 | 0 | if (mrDocShell.m_pDocument->HasExternalRefManager()) |
1810 | 0 | { |
1811 | 0 | ScExternalRefManager* pRefMgr = mrDocShell.m_pDocument->GetExternalRefManager(); |
1812 | 0 | if (pRefMgr && pRefMgr->hasExternalData()) |
1813 | 0 | { |
1814 | 0 | pRefMgr->setAllCacheTableReferencedStati( false); |
1815 | 0 | mrDocShell.m_pDocument->MarkUsedExternalReferences(); // Mark tables of external references to be written. |
1816 | 0 | } |
1817 | 0 | } |
1818 | 0 | if (mrDocShell.GetCreateMode()== SfxObjectCreateMode::STANDARD) |
1819 | 0 | mrDocShell.SfxObjectShell::SetVisArea( tools::Rectangle() ); // "Normally" worked on => no VisArea. |
1820 | 0 | } |
1821 | | |
1822 | | ScDocShell::PrepareSaveGuard::~PrepareSaveGuard() COVERITY_NOEXCEPT_FALSE |
1823 | 0 | { |
1824 | 0 | if (mrDocShell.m_pDocument->HasExternalRefManager()) |
1825 | 0 | { |
1826 | 0 | ScExternalRefManager* pRefMgr = mrDocShell.m_pDocument->GetExternalRefManager(); |
1827 | 0 | if (pRefMgr && pRefMgr->hasExternalData()) |
1828 | 0 | { |
1829 | | // Prevent accidental data loss due to lack of knowledge. |
1830 | 0 | pRefMgr->setAllCacheTableReferencedStati( true); |
1831 | 0 | } |
1832 | 0 | } |
1833 | 0 | } |
1834 | | |
1835 | | bool ScDocShell::Save() |
1836 | 0 | { |
1837 | 0 | ScRefreshTimerProtector aProt( m_pDocument->GetRefreshTimerControlAddress() ); |
1838 | |
|
1839 | 0 | PrepareSaveGuard aPrepareGuard( *this); |
1840 | |
|
1841 | 0 | if (const auto pFrame1 = SfxViewFrame::GetFirst(this)) |
1842 | 0 | { |
1843 | 0 | if (auto pSysWin = pFrame1->GetWindow().GetSystemWindow()) |
1844 | 0 | { |
1845 | 0 | pSysWin->SetAccessibleName(OUString()); |
1846 | 0 | } |
1847 | 0 | } |
1848 | | // wait cursor is handled with progress bar |
1849 | 0 | bool bRet = SfxObjectShell::Save(); |
1850 | 0 | if( bRet ) |
1851 | 0 | bRet = SaveXML( GetMedium(), nullptr ); |
1852 | 0 | return bRet; |
1853 | 0 | } |
1854 | | |
1855 | | namespace { |
1856 | | |
1857 | | /** |
1858 | | * Remove the file name from the full path, to keep only the directory path. |
1859 | | */ |
1860 | | void popFileName(OUString& rPath) |
1861 | 0 | { |
1862 | 0 | if (!rPath.isEmpty()) |
1863 | 0 | { |
1864 | 0 | INetURLObject aURLObj(rPath); |
1865 | 0 | aURLObj.removeSegment(); |
1866 | 0 | rPath = aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE); |
1867 | 0 | } |
1868 | 0 | } |
1869 | | |
1870 | | } |
1871 | | |
1872 | | void ScDocShell::TerminateEditing() |
1873 | 0 | { |
1874 | | // Commit any cell changes before saving. |
1875 | 0 | ScModule::get()->InputEnterHandler(); |
1876 | 0 | } |
1877 | | |
1878 | | bool ScDocShell::SaveAs( SfxMedium& rMedium ) |
1879 | 0 | { |
1880 | 0 | OUString aCurPath; // empty for new document that hasn't been saved. |
1881 | 0 | const SfxMedium* pCurMedium = GetMedium(); |
1882 | 0 | if (pCurMedium) |
1883 | 0 | { |
1884 | 0 | aCurPath = pCurMedium->GetName(); |
1885 | 0 | popFileName(aCurPath); |
1886 | 0 | } |
1887 | |
|
1888 | 0 | if (!aCurPath.isEmpty()) |
1889 | 0 | { |
1890 | | // current document has a path -> not a brand-new document. |
1891 | 0 | OUString aNewPath = rMedium.GetName(); |
1892 | 0 | popFileName(aNewPath); |
1893 | 0 | OUString aRel = URIHelper::simpleNormalizedMakeRelative(aCurPath, aNewPath); |
1894 | 0 | if (!aRel.isEmpty()) |
1895 | 0 | { |
1896 | | // Directory path will change before and after the save. |
1897 | 0 | m_pDocument->InvalidateStreamOnSave(); |
1898 | 0 | } |
1899 | 0 | } |
1900 | |
|
1901 | 0 | ScTabViewShell* pViewShell = GetBestViewShell(); |
1902 | 0 | bool bNeedsRehash = ScPassHashHelper::needsPassHashRegen(*m_pDocument, PASSHASH_SHA1); |
1903 | 0 | if (bNeedsRehash) |
1904 | | // legacy xls hash double-hashed by SHA1 is also supported. |
1905 | 0 | bNeedsRehash = ScPassHashHelper::needsPassHashRegen(*m_pDocument, PASSHASH_XL, PASSHASH_SHA1); |
1906 | 0 | if (bNeedsRehash) |
1907 | 0 | { // SHA256 explicitly supported in ODF 1.2, implicitly in ODF 1.1 |
1908 | 0 | bNeedsRehash = ScPassHashHelper::needsPassHashRegen(*m_pDocument, PASSHASH_SHA256); |
1909 | 0 | } |
1910 | |
|
1911 | 0 | if (pViewShell && bNeedsRehash) |
1912 | 0 | { |
1913 | 0 | bool bAutoSaveEvent = false; |
1914 | 0 | utl::MediaDescriptor lArgs(rMedium.GetArgs()); |
1915 | 0 | lArgs[utl::MediaDescriptor::PROP_AUTOSAVEEVENT] >>= bAutoSaveEvent; |
1916 | 0 | if (bAutoSaveEvent) |
1917 | 0 | { |
1918 | | // skip saving recovery file instead of showing re-type password dialog window |
1919 | 0 | SAL_WARN("sc.filter", |
1920 | 0 | "Should re-type password for own format, won't export recovery file"); |
1921 | 0 | rMedium.SetError(ERRCODE_SFX_WRONGPASSWORD); |
1922 | 0 | return false; |
1923 | 0 | } |
1924 | | |
1925 | 0 | if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_SHA1)) |
1926 | | // password re-type cancelled. Don't save the document. |
1927 | 0 | return false; |
1928 | 0 | } |
1929 | | |
1930 | 0 | ScRefreshTimerProtector aProt( m_pDocument->GetRefreshTimerControlAddress() ); |
1931 | |
|
1932 | 0 | PrepareSaveGuard aPrepareGuard( *this); |
1933 | | |
1934 | | // wait cursor is handled with progress bar |
1935 | 0 | bool bRet = SfxObjectShell::SaveAs( rMedium ); |
1936 | 0 | if (bRet) |
1937 | 0 | bRet = SaveXML( &rMedium, nullptr ); |
1938 | |
|
1939 | 0 | return bRet; |
1940 | 0 | } |
1941 | | |
1942 | | namespace { |
1943 | | |
1944 | | // Xcl-like column width measured in characters of standard font. |
1945 | | sal_Int32 lcl_ScDocShell_GetColWidthInChars( sal_uInt16 nWidth ) |
1946 | 0 | { |
1947 | 0 | double f = nWidth; |
1948 | 0 | f *= 1328.0 / 25.0; |
1949 | 0 | f += 90.0; |
1950 | 0 | f *= 1.0 / 23.0; |
1951 | 0 | f /= 256.0; |
1952 | |
|
1953 | 0 | return sal_Int32( f ); |
1954 | 0 | } |
1955 | | |
1956 | | void lcl_ScDocShell_GetFixedWidthString( OUString& rStr, const ScDocument& rDoc, |
1957 | | SCTAB nTab, SCCOL nCol, bool bValue, SvxCellHorJustify eHorJust ) |
1958 | 0 | { |
1959 | 0 | OUString aString = rStr; |
1960 | 0 | sal_Int32 nLen = lcl_ScDocShell_GetColWidthInChars( |
1961 | 0 | rDoc.GetColWidth( nCol, nTab ) ); |
1962 | | //If the text won't fit in the column |
1963 | 0 | if ( nLen < aString.getLength() ) |
1964 | 0 | { |
1965 | 0 | OUStringBuffer aReplacement; |
1966 | 0 | if (bValue) |
1967 | 0 | aReplacement.append("###"); |
1968 | 0 | else |
1969 | 0 | aReplacement.append(aString); |
1970 | | //truncate to the number of characters that should fit, even in the |
1971 | | //bValue case nLen might be < len ### |
1972 | 0 | aString = comphelper::string::truncateToLength(aReplacement, nLen).makeStringAndClear(); |
1973 | 0 | } |
1974 | 0 | if ( nLen > aString.getLength() ) |
1975 | 0 | { |
1976 | 0 | if ( bValue && eHorJust == SvxCellHorJustify::Standard ) |
1977 | 0 | eHorJust = SvxCellHorJustify::Right; |
1978 | 0 | OUStringBuffer aTmp(nLen); |
1979 | 0 | switch ( eHorJust ) |
1980 | 0 | { |
1981 | 0 | case SvxCellHorJustify::Right: |
1982 | 0 | comphelper::string::padToLength( aTmp, nLen - aString.getLength(), ' ' ); |
1983 | 0 | aString = aTmp.append(aString); |
1984 | 0 | break; |
1985 | 0 | case SvxCellHorJustify::Center: |
1986 | 0 | comphelper::string::padToLength( aTmp, (nLen - aString.getLength()) / 2, ' ' ); |
1987 | 0 | [[fallthrough]]; |
1988 | 0 | default: |
1989 | 0 | aTmp.append(aString); |
1990 | 0 | comphelper::string::padToLength( aTmp, nLen, ' ' ); |
1991 | 0 | } |
1992 | 0 | aString = aTmp.makeStringAndClear(); |
1993 | 0 | } |
1994 | 0 | rStr = aString; |
1995 | 0 | } |
1996 | | |
1997 | | void lcl_ScDocShell_WriteEmptyFixedWidthString( SvStream& rStream, |
1998 | | const ScDocument& rDoc, SCTAB nTab, SCCOL nCol ) |
1999 | 0 | { |
2000 | 0 | OUString aString; |
2001 | 0 | lcl_ScDocShell_GetFixedWidthString( aString, rDoc, nTab, nCol, false, |
2002 | 0 | SvxCellHorJustify::Standard ); |
2003 | 0 | rStream.WriteUnicodeOrByteText( aString ); |
2004 | 0 | } |
2005 | | |
2006 | | template<typename StrT, typename SepCharT> |
2007 | | sal_Int32 getTextSepPos( |
2008 | | const StrT& rStr, const ScImportOptions& rAsciiOpt, const SepCharT& rTextSep, const SepCharT& rFieldSep, bool& rNeedQuotes) |
2009 | 0 | { |
2010 | | // #i116636# quotes are needed if text delimiter (quote), field delimiter, |
2011 | | // or LF or CR is in the cell text. |
2012 | 0 | sal_Int32 nPos = rStr.indexOf(rTextSep); |
2013 | 0 | rNeedQuotes = rAsciiOpt.bQuoteAllText || (nPos >= 0) || |
2014 | 0 | (rStr.indexOf(rFieldSep) >= 0) || |
2015 | 0 | (rStr.indexOf('\n') >= 0) || |
2016 | 0 | (rStr.indexOf('\r') >= 0); |
2017 | 0 | return nPos; |
2018 | 0 | } Unexecuted instantiation: docsh.cxx:int (anonymous namespace)::getTextSepPos<rtl::OUString, char16_t>(rtl::OUString const&, ScImportOptions const&, char16_t const&, char16_t const&, bool&) Unexecuted instantiation: docsh.cxx:int (anonymous namespace)::getTextSepPos<rtl::OUString, rtl::OUString>(rtl::OUString const&, ScImportOptions const&, rtl::OUString const&, rtl::OUString const&, bool&) Unexecuted instantiation: docsh.cxx:int (anonymous namespace)::getTextSepPos<rtl::OString, rtl::OString>(rtl::OString const&, ScImportOptions const&, rtl::OString const&, rtl::OString const&, bool&) |
2019 | | |
2020 | | } |
2021 | | |
2022 | | void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt, SCTAB nTab ) |
2023 | 0 | { |
2024 | 0 | sal_Unicode cDelim = rAsciiOpt.nFieldSepCode; |
2025 | 0 | sal_Unicode cStrDelim = rAsciiOpt.nTextSepCode; |
2026 | 0 | rtl_TextEncoding eCharSet = rAsciiOpt.eCharSet; |
2027 | 0 | bool bFixedWidth = rAsciiOpt.bFixedWidth; |
2028 | 0 | bool bSaveNumberAsSuch = rAsciiOpt.bSaveNumberAsSuch; |
2029 | 0 | bool bSaveAsShown = rAsciiOpt.bSaveAsShown; |
2030 | 0 | bool bShowFormulas = rAsciiOpt.bSaveFormulas; |
2031 | 0 | bool bIncludeBOM = rAsciiOpt.bIncludeBOM; |
2032 | |
|
2033 | 0 | rtl_TextEncoding eOldCharSet = rStream.GetStreamCharSet(); |
2034 | 0 | rStream.SetStreamCharSet( eCharSet ); |
2035 | 0 | SvStreamEndian nOldNumberFormatInt = rStream.GetEndian(); |
2036 | 0 | OString aStrDelimEncoded; // only used if not Unicode |
2037 | 0 | OUString aStrDelimDecoded; // only used if context encoding |
2038 | 0 | OString aDelimEncoded; |
2039 | 0 | OUString aDelimDecoded; |
2040 | 0 | bool bContextOrNotAsciiEncoding; |
2041 | 0 | if ( eCharSet == RTL_TEXTENCODING_UNICODE ) |
2042 | 0 | { |
2043 | 0 | rStream.StartWritingUnicodeText(); |
2044 | 0 | bContextOrNotAsciiEncoding = false; |
2045 | 0 | } |
2046 | 0 | else |
2047 | 0 | { |
2048 | | // tdf#82254 - check whether to include a byte-order-mark in the output |
2049 | 0 | if (bIncludeBOM && eCharSet == RTL_TEXTENCODING_UTF8) |
2050 | 0 | rStream.WriteUChar(0xEF).WriteUChar(0xBB).WriteUChar(0xBF); |
2051 | 0 | aStrDelimEncoded = OString(&cStrDelim, 1, eCharSet); |
2052 | 0 | aDelimEncoded = OString(&cDelim, 1, eCharSet); |
2053 | 0 | rtl_TextEncodingInfo aInfo; |
2054 | 0 | aInfo.StructSize = sizeof(aInfo); |
2055 | 0 | if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) ) |
2056 | 0 | { |
2057 | 0 | bContextOrNotAsciiEncoding = |
2058 | 0 | (((aInfo.Flags & RTL_TEXTENCODING_INFO_CONTEXT) != 0) || |
2059 | 0 | ((aInfo.Flags & RTL_TEXTENCODING_INFO_ASCII) == 0)); |
2060 | 0 | if ( bContextOrNotAsciiEncoding ) |
2061 | 0 | { |
2062 | 0 | aStrDelimDecoded = OStringToOUString(aStrDelimEncoded, eCharSet); |
2063 | 0 | aDelimDecoded = OStringToOUString(aDelimEncoded, eCharSet); |
2064 | 0 | } |
2065 | 0 | } |
2066 | 0 | else |
2067 | 0 | bContextOrNotAsciiEncoding = false; |
2068 | 0 | } |
2069 | |
|
2070 | 0 | SCCOL nStartCol = 0; |
2071 | 0 | SCROW nStartRow = 0; |
2072 | 0 | SCCOL nEndCol; |
2073 | 0 | SCROW nEndRow; |
2074 | 0 | m_pDocument->GetCellArea( nTab, nEndCol, nEndRow ); |
2075 | |
|
2076 | 0 | ScProgress aProgress( this, ScResId( STR_SAVE_DOC ), nEndRow, true ); |
2077 | |
|
2078 | 0 | OUString aString; |
2079 | |
|
2080 | 0 | bool bTabProtect = m_pDocument->IsTabProtected( nTab ); |
2081 | |
|
2082 | 0 | SCCOL nCol; |
2083 | 0 | SCROW nRow; |
2084 | | |
2085 | | // Treat the top left cell separator "sep=" special. |
2086 | | // Here nStartRow == 0 && nStartCol == 0 |
2087 | 0 | if (!bFixedWidth && cDelim != 0) |
2088 | 0 | { |
2089 | | // First row iterator. |
2090 | 0 | ScHorizontalCellIterator aIter( *m_pDocument, nTab, nStartCol, nStartRow, nEndCol, nStartRow); |
2091 | 0 | ScRefCellValue* pCell; |
2092 | | // Must be first column and all following cells on this row must be |
2093 | | // empty to fiddle with "sep=". |
2094 | 0 | if ((pCell = aIter.GetNext( nCol, nRow)) != nullptr && nCol == nStartCol && !aIter.GetNext( nCol, nRow)) |
2095 | 0 | { |
2096 | 0 | if (pCell->getType() == CELLTYPE_STRING) |
2097 | 0 | { |
2098 | 0 | aString = pCell->getSharedString()->getString(); |
2099 | 0 | if (aString.getLength() <= 5 && aString.startsWithIgnoreAsciiCase("sep=")) |
2100 | 0 | { |
2101 | | // Cell content is /^sep=.?$/ so write current separator. |
2102 | | // Force the quote character to '"' regardless what is set |
2103 | | // for export because that is the only one recognized on |
2104 | | // import. |
2105 | 0 | aString = "sep=" + OUStringChar(cDelim); |
2106 | 0 | if (cStrDelim != 0) |
2107 | 0 | rStream.WriteUniOrByteChar( '"', eCharSet); |
2108 | 0 | rStream.WriteUnicodeOrByteText(aString, eCharSet); |
2109 | 0 | if (cStrDelim != 0) |
2110 | 0 | rStream.WriteUniOrByteChar( '"', eCharSet); |
2111 | 0 | endlub( rStream ); |
2112 | 0 | ++nStartRow; |
2113 | 0 | } |
2114 | 0 | } |
2115 | 0 | } |
2116 | 0 | } |
2117 | |
|
2118 | 0 | SCCOL nNextCol = nStartCol; |
2119 | 0 | SCROW nNextRow = nStartRow; |
2120 | 0 | SCCOL nEmptyCol; |
2121 | 0 | SCROW nEmptyRow; |
2122 | 0 | ScInterpreterContext& rContext = m_pDocument->GetNonThreadedContext(); |
2123 | |
|
2124 | 0 | ScHorizontalCellIterator aIter( *m_pDocument, nTab, nStartCol, nStartRow, |
2125 | 0 | nEndCol, nEndRow ); |
2126 | 0 | ScRefCellValue* pCell; |
2127 | 0 | while ( ( pCell = aIter.GetNext( nCol, nRow ) ) != nullptr ) |
2128 | 0 | { |
2129 | 0 | bool bProgress = false; // only upon line change |
2130 | 0 | if ( nNextRow < nRow ) |
2131 | 0 | { // empty rows or/and empty columns up to end of row |
2132 | 0 | bProgress = true; |
2133 | 0 | for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ ) |
2134 | 0 | { // remaining columns of last row |
2135 | 0 | if ( bFixedWidth ) |
2136 | 0 | lcl_ScDocShell_WriteEmptyFixedWidthString( rStream, |
2137 | 0 | *m_pDocument, nTab, nEmptyCol ); |
2138 | 0 | else if ( cDelim != 0 ) |
2139 | 0 | rStream.WriteUniOrByteChar( cDelim ); |
2140 | 0 | } |
2141 | 0 | endlub( rStream ); |
2142 | 0 | nNextRow++; |
2143 | 0 | for ( nEmptyRow = nNextRow; nEmptyRow < nRow; nEmptyRow++ ) |
2144 | 0 | { // completely empty rows |
2145 | 0 | for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ ) |
2146 | 0 | { |
2147 | 0 | if ( bFixedWidth ) |
2148 | 0 | lcl_ScDocShell_WriteEmptyFixedWidthString( rStream, |
2149 | 0 | *m_pDocument, nTab, nEmptyCol ); |
2150 | 0 | else if ( cDelim != 0 ) |
2151 | 0 | rStream.WriteUniOrByteChar( cDelim ); |
2152 | 0 | } |
2153 | 0 | endlub( rStream ); |
2154 | 0 | } |
2155 | 0 | for ( nEmptyCol = nStartCol; nEmptyCol < nCol; nEmptyCol++ ) |
2156 | 0 | { // empty columns at beginning of row |
2157 | 0 | if ( bFixedWidth ) |
2158 | 0 | lcl_ScDocShell_WriteEmptyFixedWidthString( rStream, |
2159 | 0 | *m_pDocument, nTab, nEmptyCol ); |
2160 | 0 | else if ( cDelim != 0 ) |
2161 | 0 | rStream.WriteUniOrByteChar( cDelim ); |
2162 | 0 | } |
2163 | 0 | nNextRow = nRow; |
2164 | 0 | } |
2165 | 0 | else if ( nNextCol < nCol ) |
2166 | 0 | { // empty columns in same row |
2167 | 0 | for ( nEmptyCol = nNextCol; nEmptyCol < nCol; nEmptyCol++ ) |
2168 | 0 | { // columns in between |
2169 | 0 | if ( bFixedWidth ) |
2170 | 0 | lcl_ScDocShell_WriteEmptyFixedWidthString( rStream, |
2171 | 0 | *m_pDocument, nTab, nEmptyCol ); |
2172 | 0 | else if ( cDelim != 0 ) |
2173 | 0 | rStream.WriteUniOrByteChar( cDelim ); |
2174 | 0 | } |
2175 | 0 | } |
2176 | 0 | if ( nCol == nEndCol ) |
2177 | 0 | { |
2178 | 0 | bProgress = true; |
2179 | 0 | nNextCol = nStartCol; |
2180 | 0 | nNextRow = nRow + 1; |
2181 | 0 | } |
2182 | 0 | else |
2183 | 0 | nNextCol = nCol + 1; |
2184 | |
|
2185 | 0 | CellType eType = pCell->getType(); |
2186 | 0 | ScAddress aPos(nCol, nRow, nTab); |
2187 | 0 | if ( bTabProtect ) |
2188 | 0 | { |
2189 | 0 | const ScProtectionAttr* pProtAttr = |
2190 | 0 | m_pDocument->GetAttr( nCol, nRow, nTab, ATTR_PROTECTION ); |
2191 | 0 | if ( pProtAttr->GetHideCell() || |
2192 | 0 | ( eType == CELLTYPE_FORMULA && bShowFormulas && |
2193 | 0 | pProtAttr->GetHideFormula() ) ) |
2194 | 0 | eType = CELLTYPE_NONE; // hide |
2195 | 0 | } |
2196 | 0 | bool bForceQuotes = false; |
2197 | 0 | bool bString; |
2198 | 0 | switch ( eType ) |
2199 | 0 | { |
2200 | 0 | case CELLTYPE_NONE: |
2201 | 0 | aString.clear(); |
2202 | 0 | bString = false; |
2203 | 0 | break; |
2204 | 0 | case CELLTYPE_FORMULA : |
2205 | 0 | { |
2206 | 0 | FormulaError nErrCode; |
2207 | 0 | if ( bShowFormulas ) |
2208 | 0 | { |
2209 | 0 | aString = pCell->getFormula()->GetFormula(); |
2210 | 0 | bString = true; |
2211 | 0 | } |
2212 | 0 | else if ((nErrCode = pCell->getFormula()->GetErrCode()) != FormulaError::NONE) |
2213 | 0 | { |
2214 | 0 | aString = ScGlobal::GetErrorString( nErrCode ); |
2215 | 0 | bString = true; |
2216 | 0 | } |
2217 | 0 | else if (pCell->getFormula()->IsValue()) |
2218 | 0 | { |
2219 | 0 | sal_uInt32 nFormat = m_pDocument->GetNumberFormat(ScRange(aPos)); |
2220 | 0 | if ( bFixedWidth || bSaveAsShown ) |
2221 | 0 | { |
2222 | 0 | const Color* pDummy; |
2223 | 0 | aString = ScCellFormat::GetString(*pCell, nFormat, &pDummy, &rContext, *m_pDocument); |
2224 | 0 | bString = bSaveAsShown && rContext.NFIsTextFormat( nFormat); |
2225 | 0 | } |
2226 | 0 | else |
2227 | 0 | { |
2228 | 0 | aString = ScCellFormat::GetInputString(*pCell, nFormat, &rContext, *m_pDocument); |
2229 | 0 | bString = bForceQuotes = !bSaveNumberAsSuch; |
2230 | 0 | } |
2231 | 0 | } |
2232 | 0 | else |
2233 | 0 | { |
2234 | 0 | if ( bSaveAsShown ) |
2235 | 0 | { |
2236 | 0 | sal_uInt32 nFormat = m_pDocument->GetNumberFormat(ScRange(aPos)); |
2237 | 0 | const Color* pDummy; |
2238 | 0 | aString = ScCellFormat::GetString(*pCell, nFormat, &pDummy, &rContext, *m_pDocument); |
2239 | 0 | } |
2240 | 0 | else |
2241 | 0 | aString = pCell->getFormula()->GetString().getString(); |
2242 | 0 | bString = true; |
2243 | 0 | } |
2244 | 0 | } |
2245 | 0 | break; |
2246 | 0 | case CELLTYPE_STRING : |
2247 | 0 | if ( bSaveAsShown ) |
2248 | 0 | { |
2249 | 0 | sal_uInt32 nFormat = m_pDocument->GetNumberFormat(ScRange(aPos)); |
2250 | 0 | const Color* pDummy; |
2251 | 0 | aString = ScCellFormat::GetString(*pCell, nFormat, &pDummy, &rContext, *m_pDocument); |
2252 | 0 | } |
2253 | 0 | else |
2254 | 0 | aString = pCell->getSharedString()->getString(); |
2255 | 0 | bString = true; |
2256 | 0 | break; |
2257 | 0 | case CELLTYPE_EDIT : |
2258 | 0 | { |
2259 | 0 | const EditTextObject* pObj = pCell->getEditText(); |
2260 | 0 | EditEngine& rEngine = m_pDocument->GetEditEngine(); |
2261 | 0 | rEngine.SetText( *pObj); |
2262 | 0 | aString = rEngine.GetText(); // including LF |
2263 | 0 | bString = true; |
2264 | 0 | } |
2265 | 0 | break; |
2266 | 0 | case CELLTYPE_VALUE : |
2267 | 0 | { |
2268 | 0 | sal_uInt32 nFormat = m_pDocument->GetNumberFormat( nCol, nRow, nTab ); |
2269 | 0 | if ( bFixedWidth || bSaveAsShown ) |
2270 | 0 | { |
2271 | 0 | const Color* pDummy; |
2272 | 0 | aString = ScCellFormat::GetString(*pCell, nFormat, &pDummy, &rContext, *m_pDocument); |
2273 | 0 | bString = bSaveAsShown && rContext.NFIsTextFormat( nFormat); |
2274 | 0 | } |
2275 | 0 | else |
2276 | 0 | { |
2277 | 0 | aString = ScCellFormat::GetInputString(*pCell, nFormat, &rContext, *m_pDocument); |
2278 | 0 | bString = bForceQuotes = !bSaveNumberAsSuch; |
2279 | 0 | } |
2280 | 0 | } |
2281 | 0 | break; |
2282 | 0 | default: |
2283 | 0 | OSL_FAIL( "ScDocShell::AsciiSave: unknown CellType" ); |
2284 | 0 | aString.clear(); |
2285 | 0 | bString = false; |
2286 | 0 | } |
2287 | | |
2288 | 0 | if ( bFixedWidth ) |
2289 | 0 | { |
2290 | 0 | SvxCellHorJustify eHorJust = |
2291 | 0 | m_pDocument->GetAttr( nCol, nRow, nTab, ATTR_HOR_JUSTIFY )->GetValue(); |
2292 | 0 | lcl_ScDocShell_GetFixedWidthString( aString, *m_pDocument, nTab, nCol, |
2293 | 0 | !bString, eHorJust ); |
2294 | 0 | rStream.WriteUnicodeOrByteText( aString ); |
2295 | 0 | } |
2296 | 0 | else |
2297 | 0 | { |
2298 | 0 | OUString aUniString = aString;// TODO: remove that later |
2299 | 0 | if (!bString && cStrDelim != 0 && !aUniString.isEmpty()) |
2300 | 0 | { |
2301 | 0 | sal_Unicode c = aUniString[0]; |
2302 | 0 | bString = (c == cStrDelim || c == ' ' || |
2303 | 0 | aUniString.endsWith(" ") || |
2304 | 0 | aUniString.indexOf(cStrDelim) >= 0); |
2305 | 0 | if (!bString && cDelim != 0) |
2306 | 0 | bString = (aUniString.indexOf(cDelim) >= 0); |
2307 | 0 | } |
2308 | 0 | if ( bString ) |
2309 | 0 | { |
2310 | 0 | if ( cStrDelim != 0 ) //@ BugId 55355 |
2311 | 0 | { |
2312 | 0 | if ( eCharSet == RTL_TEXTENCODING_UNICODE ) |
2313 | 0 | { |
2314 | 0 | bool bNeedQuotes = false; |
2315 | 0 | sal_Int32 nPos = getTextSepPos(aUniString, rAsciiOpt, cStrDelim, cDelim, bNeedQuotes); |
2316 | 0 | if (nPos >= 0) |
2317 | 0 | { |
2318 | 0 | OUString strFrom(cStrDelim); |
2319 | 0 | OUString strTo = strFrom + strFrom; |
2320 | 0 | aUniString = aUniString.replaceAll(strFrom, strTo); |
2321 | 0 | } |
2322 | |
|
2323 | 0 | if ( bNeedQuotes || bForceQuotes ) |
2324 | 0 | rStream.WriteUniOrByteChar( cStrDelim, eCharSet ); |
2325 | 0 | rStream.WriteUnicodeOrByteText(aUniString, eCharSet); |
2326 | 0 | if ( bNeedQuotes || bForceQuotes ) |
2327 | 0 | rStream.WriteUniOrByteChar( cStrDelim, eCharSet ); |
2328 | 0 | } |
2329 | 0 | else |
2330 | 0 | { |
2331 | | // This is nasty. The Unicode to byte encoding |
2332 | | // may convert typographical quotation marks to ASCII |
2333 | | // quotation marks, which may interfere with the delimiter, |
2334 | | // so we have to escape delimiters after the string has |
2335 | | // been encoded. Since this may happen also with UTF-8 |
2336 | | // encoded typographical quotation marks if such was |
2337 | | // specified as a delimiter we have to check for the full |
2338 | | // encoded delimiter string, not just one character. |
2339 | | // Now for RTL_TEXTENCODING_ISO_2022_... and similar brain |
2340 | | // dead encodings where one code point (and especially a |
2341 | | // low ASCII value) may represent different characters, we |
2342 | | // have to convert forth and back and forth again. Same for |
2343 | | // UTF-7 since it is a context sensitive encoding too. |
2344 | |
|
2345 | 0 | if ( bContextOrNotAsciiEncoding ) |
2346 | 0 | { |
2347 | | // to byte encoding |
2348 | 0 | OString aStrEnc = OUStringToOString(aUniString, eCharSet); |
2349 | | // back to Unicode |
2350 | 0 | OUString aStrDec = OStringToOUString(aStrEnc, eCharSet); |
2351 | | |
2352 | | // search on re-decoded string |
2353 | 0 | bool bNeedQuotes = false; |
2354 | 0 | sal_Int32 nPos = getTextSepPos(aStrDec, rAsciiOpt, aStrDelimDecoded, aDelimDecoded, bNeedQuotes); |
2355 | 0 | if (nPos >= 0) |
2356 | 0 | { |
2357 | 0 | OUString strTo = aStrDelimDecoded + aStrDelimDecoded; |
2358 | 0 | aStrDec = aStrDec.replaceAll(aStrDelimDecoded, strTo); |
2359 | 0 | } |
2360 | | |
2361 | | // write byte re-encoded |
2362 | 0 | if ( bNeedQuotes || bForceQuotes ) |
2363 | 0 | rStream.WriteUniOrByteChar( cStrDelim, eCharSet ); |
2364 | 0 | rStream.WriteUnicodeOrByteText( aStrDec, eCharSet ); |
2365 | 0 | if ( bNeedQuotes || bForceQuotes ) |
2366 | 0 | rStream.WriteUniOrByteChar( cStrDelim, eCharSet ); |
2367 | 0 | } |
2368 | 0 | else |
2369 | 0 | { |
2370 | 0 | OString aStrEnc = OUStringToOString(aUniString, eCharSet); |
2371 | | |
2372 | | // search on encoded string |
2373 | 0 | bool bNeedQuotes = false; |
2374 | 0 | sal_Int32 nPos = getTextSepPos(aStrEnc, rAsciiOpt, aStrDelimEncoded, aDelimEncoded, bNeedQuotes); |
2375 | 0 | if (nPos >= 0) |
2376 | 0 | { |
2377 | 0 | OString strTo = aStrDelimEncoded + aStrDelimEncoded; |
2378 | 0 | aStrEnc = aStrEnc.replaceAll(aStrDelimEncoded, strTo); |
2379 | 0 | } |
2380 | | |
2381 | | // write byte encoded |
2382 | 0 | if ( bNeedQuotes || bForceQuotes ) |
2383 | 0 | rStream.WriteBytes( |
2384 | 0 | aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength()); |
2385 | 0 | rStream.WriteBytes(aStrEnc.getStr(), aStrEnc.getLength()); |
2386 | 0 | if ( bNeedQuotes || bForceQuotes ) |
2387 | 0 | rStream.WriteBytes( |
2388 | 0 | aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength()); |
2389 | 0 | } |
2390 | 0 | } |
2391 | 0 | } |
2392 | 0 | else |
2393 | 0 | rStream.WriteUnicodeOrByteText( aUniString ); |
2394 | 0 | } |
2395 | 0 | else |
2396 | 0 | rStream.WriteUnicodeOrByteText( aUniString ); |
2397 | 0 | } |
2398 | |
|
2399 | 0 | if( nCol < nEndCol ) |
2400 | 0 | { |
2401 | 0 | if(cDelim!=0) //@ BugId 55355 |
2402 | 0 | rStream.WriteUniOrByteChar( cDelim ); |
2403 | 0 | } |
2404 | 0 | else |
2405 | 0 | endlub( rStream ); |
2406 | |
|
2407 | 0 | if ( bProgress ) |
2408 | 0 | aProgress.SetStateOnPercent( nRow ); |
2409 | 0 | } |
2410 | | |
2411 | | // write out empty if requested |
2412 | 0 | if ( nNextRow <= nEndRow ) |
2413 | 0 | { |
2414 | 0 | for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ ) |
2415 | 0 | { // remaining empty columns of last row |
2416 | 0 | if ( bFixedWidth ) |
2417 | 0 | lcl_ScDocShell_WriteEmptyFixedWidthString( rStream, |
2418 | 0 | *m_pDocument, nTab, nEmptyCol ); |
2419 | 0 | else if ( cDelim != 0 ) |
2420 | 0 | rStream.WriteUniOrByteChar( cDelim ); |
2421 | 0 | } |
2422 | 0 | endlub( rStream ); |
2423 | 0 | nNextRow++; |
2424 | 0 | } |
2425 | 0 | for ( nEmptyRow = nNextRow; nEmptyRow <= nEndRow; nEmptyRow++ ) |
2426 | 0 | { // entire empty rows |
2427 | 0 | for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ ) |
2428 | 0 | { |
2429 | 0 | if ( bFixedWidth ) |
2430 | 0 | lcl_ScDocShell_WriteEmptyFixedWidthString( rStream, |
2431 | 0 | *m_pDocument, nTab, nEmptyCol ); |
2432 | 0 | else if ( cDelim != 0 ) |
2433 | 0 | rStream.WriteUniOrByteChar( cDelim ); |
2434 | 0 | } |
2435 | 0 | endlub( rStream ); |
2436 | 0 | } |
2437 | |
|
2438 | 0 | rStream.SetStreamCharSet( eOldCharSet ); |
2439 | 0 | rStream.SetEndian( nOldNumberFormatInt ); |
2440 | 0 | } |
2441 | | |
2442 | | bool ScDocShell::ConvertTo( SfxMedium &rMed ) |
2443 | 0 | { |
2444 | 0 | ScRefreshTimerProtector aProt( m_pDocument->GetRefreshTimerControlAddress() ); |
2445 | | |
2446 | | // #i6500# don't call DoEnterHandler here (doesn't work with AutoSave), |
2447 | | // it's already in ExecuteSave (as for Save and SaveAs) |
2448 | |
|
2449 | 0 | if (m_pAutoStyleList) |
2450 | 0 | m_pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now |
2451 | 0 | if (GetCreateMode()== SfxObjectCreateMode::STANDARD) |
2452 | 0 | SfxObjectShell::SetVisArea( tools::Rectangle() ); // Edited normally -> no VisArea |
2453 | |
|
2454 | 0 | OSL_ENSURE( rMed.GetFilter(), "Filter == 0" ); |
2455 | |
|
2456 | 0 | bool bRet = false; |
2457 | 0 | OUString aFltName = rMed.GetFilter()->GetFilterName(); |
2458 | |
|
2459 | 0 | if (aFltName == pFilterXML) |
2460 | 0 | { |
2461 | | //TODO/LATER: this shouldn't happen! |
2462 | 0 | OSL_FAIL("XML filter in ConvertFrom?!"); |
2463 | 0 | bRet = SaveXML( &rMed, nullptr ); |
2464 | 0 | } |
2465 | 0 | else if (aFltName == pFilterExcel5 || aFltName == pFilterExcel95 || |
2466 | 0 | aFltName == pFilterExcel97 || aFltName == pFilterEx5Temp || |
2467 | 0 | aFltName == pFilterEx95Temp || aFltName == pFilterEx97Temp) |
2468 | 0 | { |
2469 | 0 | weld::WaitObject aWait( GetActiveDialogParent() ); |
2470 | |
|
2471 | 0 | bool bDoSave = true; |
2472 | 0 | if( ScTabViewShell* pViewShell = GetBestViewShell() ) |
2473 | 0 | { |
2474 | 0 | ScExtDocOptions* pExtDocOpt = m_pDocument->GetExtDocOptions(); |
2475 | 0 | if( !pExtDocOpt ) |
2476 | 0 | { |
2477 | 0 | m_pDocument->SetExtDocOptions( std::make_unique<ScExtDocOptions>() ); |
2478 | 0 | pExtDocOpt = m_pDocument->GetExtDocOptions(); |
2479 | 0 | } |
2480 | 0 | pViewShell->GetViewData().WriteExtOptions( *pExtDocOpt ); |
2481 | | |
2482 | | /* #i104990# If the imported document contains a medium |
2483 | | password, determine if we can save it, otherwise ask the users |
2484 | | whether they want to save without it. */ |
2485 | 0 | if( (rMed.GetFilter()->GetFilterFlags() & SfxFilterFlags::ENCRYPTION) == SfxFilterFlags::NONE ) |
2486 | 0 | { |
2487 | 0 | SfxItemSet& rItemSet = rMed.GetItemSet(); |
2488 | 0 | if( rItemSet.GetItemState( SID_PASSWORD ) == SfxItemState::SET ) |
2489 | 0 | { |
2490 | 0 | bDoSave = ScWarnPassword::WarningOnPassword( rMed ); |
2491 | | // #i42858# remove password from medium (warn only one time) |
2492 | 0 | if( bDoSave ) |
2493 | 0 | rItemSet.ClearItem( SID_PASSWORD ); |
2494 | 0 | } |
2495 | 0 | } |
2496 | |
|
2497 | 0 | if( bDoSave ) |
2498 | 0 | { |
2499 | 0 | bool bNeedRetypePassDlg = ScPassHashHelper::needsPassHashRegen( *m_pDocument, PASSHASH_XL ); |
2500 | 0 | bDoSave = !bNeedRetypePassDlg || pViewShell->ExecuteRetypePassDlg( PASSHASH_XL ); |
2501 | 0 | } |
2502 | 0 | } |
2503 | |
|
2504 | 0 | if( bDoSave ) |
2505 | 0 | { |
2506 | 0 | ExportFormatExcel eFormat = ExpBiff5; |
2507 | 0 | if( aFltName == pFilterExcel97 || aFltName == pFilterEx97Temp ) |
2508 | 0 | eFormat = ExpBiff8; |
2509 | 0 | ErrCode eError = ScFormatFilter::Get().ScExportExcel5( rMed, m_pDocument.get(), eFormat, RTL_TEXTENCODING_MS_1252 ); |
2510 | |
|
2511 | 0 | if( eError && !GetErrorIgnoreWarning() ) |
2512 | 0 | SetError(eError); |
2513 | | |
2514 | | // don't return false for warnings |
2515 | 0 | bRet = eError.IsWarning() || (eError == ERRCODE_NONE); |
2516 | 0 | } |
2517 | 0 | else |
2518 | 0 | { |
2519 | | // export aborted, i.e. "Save without password" warning |
2520 | 0 | SetError(ERRCODE_ABORT); |
2521 | 0 | } |
2522 | 0 | } |
2523 | 0 | else if (aFltName == SC_TEXT_CSV_FILTER_NAME) |
2524 | 0 | { |
2525 | 0 | OUString sItStr; |
2526 | 0 | if ( const SfxStringItem* pOptionsItem = rMed.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) |
2527 | 0 | { |
2528 | 0 | sItStr = pOptionsItem->GetValue(); |
2529 | 0 | } |
2530 | |
|
2531 | 0 | if ( sItStr.isEmpty() ) |
2532 | 0 | { |
2533 | | // default for ascii export (from API without options): |
2534 | | // UTF-8 encoding, comma, double quotes |
2535 | |
|
2536 | 0 | ScImportOptions aDefOptions(',', '"', RTL_TEXTENCODING_UTF8); |
2537 | 0 | sItStr = aDefOptions.BuildString(); |
2538 | 0 | } |
2539 | |
|
2540 | 0 | weld::WaitObject aWait( GetActiveDialogParent() ); |
2541 | 0 | ScImportOptions aOptions( sItStr ); |
2542 | |
|
2543 | 0 | if (aOptions.nSheetToExport) |
2544 | 0 | { |
2545 | | // Only from command line --convert-to |
2546 | 0 | bRet = true; |
2547 | | |
2548 | | // Verbose only from command line, not UI (in case we actually |
2549 | | // implement that) nor macro filter options. |
2550 | 0 | bool bVerbose = false; |
2551 | 0 | const css::uno::Sequence<css::beans::PropertyValue> & rArgs = rMed.GetArgs(); |
2552 | 0 | const auto pProp = std::find_if( rArgs.begin(), rArgs.end(), |
2553 | 0 | [](const css::beans::PropertyValue& rProp) { return rProp.Name == "ConversionRequestOrigin"; }); |
2554 | 0 | if (pProp != rArgs.end()) |
2555 | 0 | { |
2556 | 0 | OUString aOrigin; |
2557 | 0 | pProp->Value >>= aOrigin; |
2558 | 0 | bVerbose = (aOrigin == "CommandLine"); |
2559 | 0 | } |
2560 | |
|
2561 | 0 | SCTAB nStartTab; |
2562 | 0 | SCTAB nCount = m_pDocument->GetTableCount(); |
2563 | 0 | if (aOptions.nSheetToExport == -1) |
2564 | 0 | { |
2565 | | // All sheets. |
2566 | 0 | nStartTab = 0; |
2567 | 0 | } |
2568 | 0 | else if (0 < aOptions.nSheetToExport && aOptions.nSheetToExport <= nCount) |
2569 | 0 | { |
2570 | | // One sheet, 1-based. |
2571 | 0 | nCount = aOptions.nSheetToExport; |
2572 | 0 | nStartTab = nCount - 1; |
2573 | 0 | } |
2574 | 0 | else |
2575 | 0 | { |
2576 | | // Usage error, no export but log. |
2577 | 0 | if (bVerbose) |
2578 | 0 | { |
2579 | 0 | if (aOptions.nSheetToExport < 0) |
2580 | 0 | std::cout << "Bad sheet number string given." << std::endl; |
2581 | 0 | else |
2582 | 0 | std::cout << "No sheet number " << aOptions.nSheetToExport |
2583 | 0 | << ", number of sheets is " << nCount << std::endl; |
2584 | 0 | } |
2585 | 0 | nStartTab = 0; |
2586 | 0 | nCount = 0; |
2587 | 0 | SetError(SCERR_EXPORT_DATA); |
2588 | 0 | bRet = false; |
2589 | 0 | } |
2590 | |
|
2591 | 0 | INetURLObject aURLObject(rMed.GetURLObject()); |
2592 | 0 | OUString sExt = aURLObject.CutExtension(); |
2593 | 0 | OUString sBaseName = aURLObject.GetLastName(); |
2594 | 0 | aURLObject.CutLastName(); |
2595 | |
|
2596 | 0 | for (SCTAB i = nStartTab; i < nCount; ++i) |
2597 | 0 | { |
2598 | 0 | OUString sTabName; |
2599 | 0 | if (!m_pDocument->GetName(i, sTabName)) |
2600 | 0 | sTabName = OUString::number(i); |
2601 | 0 | INetURLObject aSheetURLObject(aURLObject); |
2602 | 0 | OUString sFileName = sBaseName + "-" + sTabName; |
2603 | 0 | if (!sExt.isEmpty()) |
2604 | 0 | sFileName = sFileName + "." + sExt; |
2605 | 0 | aSheetURLObject.Append(sFileName); |
2606 | | |
2607 | | // log similar to DispatchWatcher::executeDispatchRequests |
2608 | 0 | OUString aOutFile = aSheetURLObject.GetMainURL(INetURLObject::DecodeMechanism::NONE); |
2609 | 0 | if (bVerbose) |
2610 | 0 | { |
2611 | 0 | OUString aDisplayedName; |
2612 | 0 | if (osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL(aOutFile, aDisplayedName)) |
2613 | 0 | aDisplayedName = aOutFile; |
2614 | 0 | std::cout << "Writing sheet " << OUStringToOString(sTabName, osl_getThreadTextEncoding()) << " -> " |
2615 | 0 | << OUStringToOString(aDisplayedName, osl_getThreadTextEncoding()) |
2616 | 0 | << std::endl; |
2617 | |
|
2618 | 0 | if (FStatHelper::IsDocument(aOutFile)) |
2619 | 0 | std::cout << "Overwriting: " << OUStringToOString(aDisplayedName, osl_getThreadTextEncoding()) |
2620 | 0 | << std::endl ; |
2621 | 0 | } |
2622 | |
|
2623 | 0 | std::unique_ptr<SvStream> xStm = ::utl::UcbStreamHelper::CreateStream(aOutFile, StreamMode::TRUNC | StreamMode::WRITE); |
2624 | 0 | if (!xStm) |
2625 | 0 | { |
2626 | 0 | SetError(ERRCODE_IO_CANTCREATE); |
2627 | 0 | bRet = false; |
2628 | 0 | break; |
2629 | 0 | } |
2630 | 0 | AsciiSave(*xStm, aOptions, i); |
2631 | 0 | } |
2632 | 0 | } |
2633 | 0 | else |
2634 | 0 | { |
2635 | 0 | SvStream* pStream = rMed.GetOutStream(); |
2636 | 0 | if (pStream) |
2637 | 0 | { |
2638 | 0 | AsciiSave(*pStream, aOptions, GetSaveTab()); |
2639 | 0 | bRet = true; |
2640 | |
|
2641 | 0 | if (m_pDocument->GetTableCount() > 1) |
2642 | 0 | { |
2643 | 0 | if (!rMed.GetErrorIgnoreWarning() && ScModule::get()->GetInputOptions().GetWarnActiveSheet()) |
2644 | 0 | { |
2645 | 0 | if (ScTabViewShell* pViewShell = GetBestViewShell()) |
2646 | 0 | pViewShell->ExecuteOnlyActiveSheetSavedDlg(); |
2647 | 0 | } |
2648 | 0 | } |
2649 | 0 | } |
2650 | 0 | } |
2651 | 0 | } |
2652 | 0 | else if (aFltName == pFilterDBase) |
2653 | 0 | { |
2654 | 0 | OUString sCharSet; |
2655 | 0 | if ( const SfxStringItem* pOptionsItem = rMed.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) |
2656 | 0 | { |
2657 | 0 | sCharSet = pOptionsItem->GetValue(); |
2658 | 0 | } |
2659 | |
|
2660 | 0 | if (sCharSet.isEmpty()) |
2661 | 0 | { |
2662 | | // default for dBase export (from API without options): |
2663 | | // IBM_850 encoding |
2664 | |
|
2665 | 0 | sCharSet = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 ); |
2666 | 0 | } |
2667 | |
|
2668 | 0 | weld::WaitObject aWait( GetActiveDialogParent() ); |
2669 | | // Hack so that Sba can overwrite the opened TempFile. |
2670 | 0 | rMed.CloseOutStream(); |
2671 | 0 | bool bHasMemo = false; |
2672 | |
|
2673 | 0 | ErrCodeMsg eError = DBaseExport( |
2674 | 0 | rMed.GetPhysicalName(), ScGlobal::GetCharsetValue(sCharSet), bHasMemo); |
2675 | |
|
2676 | 0 | INetURLObject aTmpFile( rMed.GetPhysicalName(), INetProtocol::File ); |
2677 | 0 | if ( bHasMemo ) |
2678 | 0 | aTmpFile.setExtension(u"dbt"); |
2679 | 0 | if ( eError != ERRCODE_NONE && !eError.IsWarning() ) |
2680 | 0 | { |
2681 | 0 | if (!GetErrorIgnoreWarning()) |
2682 | 0 | SetError(eError); |
2683 | 0 | if ( bHasMemo && IsDocument( aTmpFile ) ) |
2684 | 0 | KillFile( aTmpFile ); |
2685 | 0 | } |
2686 | 0 | else |
2687 | 0 | { |
2688 | 0 | bRet = true; |
2689 | 0 | if ( bHasMemo ) |
2690 | 0 | { |
2691 | 0 | const SfxStringItem* pNameItem = rMed.GetItemSet().GetItem<SfxStringItem>( SID_FILE_NAME ); |
2692 | 0 | assert(pNameItem && "SID_FILE_NAME is required"); |
2693 | 0 | INetURLObject aDbtFile( pNameItem->GetValue(), INetProtocol::File ); |
2694 | 0 | aDbtFile.setExtension(u"dbt"); |
2695 | | |
2696 | | // tdf#40713: don't lose dbt file |
2697 | | // if aDbtFile corresponds exactly to aTmpFile, we just have to return |
2698 | 0 | if (aDbtFile.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ) == |
2699 | 0 | aTmpFile.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous )) |
2700 | 0 | { |
2701 | 0 | if (eError != ERRCODE_NONE && !GetErrorIgnoreWarning()) |
2702 | 0 | SetError(eError); |
2703 | 0 | return bRet; |
2704 | 0 | } |
2705 | | |
2706 | 0 | if ( IsDocument( aDbtFile ) && !KillFile( aDbtFile ) ) |
2707 | 0 | bRet = false; |
2708 | 0 | if ( bRet && !MoveFile( aTmpFile, aDbtFile ) ) |
2709 | 0 | bRet = false; |
2710 | 0 | if ( !bRet ) |
2711 | 0 | { |
2712 | 0 | KillFile( aTmpFile ); |
2713 | 0 | if (eError == ERRCODE_NONE || eError.IsWarning()) |
2714 | 0 | eError = SCERR_EXPORT_DATA; |
2715 | 0 | } |
2716 | 0 | } |
2717 | 0 | if (eError != ERRCODE_NONE && !GetErrorIgnoreWarning()) |
2718 | 0 | SetError(eError); |
2719 | 0 | } |
2720 | 0 | } |
2721 | 0 | else if (aFltName == pFilterDif) |
2722 | 0 | { |
2723 | 0 | SvStream* pStream = rMed.GetOutStream(); |
2724 | 0 | if (pStream) |
2725 | 0 | { |
2726 | 0 | OUString sItStr; |
2727 | 0 | if ( const SfxStringItem* pOptionsItem = rMed.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) |
2728 | 0 | { |
2729 | 0 | sItStr = pOptionsItem->GetValue(); |
2730 | 0 | } |
2731 | |
|
2732 | 0 | if (sItStr.isEmpty()) |
2733 | 0 | { |
2734 | | // default for DIF export (from API without options): |
2735 | | // ISO8859-1/MS_1252 encoding |
2736 | |
|
2737 | 0 | sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 ); |
2738 | 0 | } |
2739 | |
|
2740 | 0 | weld::WaitObject aWait( GetActiveDialogParent() ); |
2741 | 0 | ScFormatFilter::Get().ScExportDif( *pStream, *m_pDocument, ScAddress(0,0,0), |
2742 | 0 | ScGlobal::GetCharsetValue(sItStr) ); |
2743 | 0 | bRet = true; |
2744 | |
|
2745 | 0 | if (m_pDocument->GetTableCount() > 1) |
2746 | 0 | if (!rMed.GetErrorIgnoreWarning() && ScModule::get()->GetInputOptions().GetWarnActiveSheet()) |
2747 | 0 | rMed.SetError(SCWARN_EXPORT_ASCII); |
2748 | 0 | } |
2749 | 0 | } |
2750 | 0 | else if (aFltName == pFilterSylk) |
2751 | 0 | { |
2752 | 0 | SvStream* pStream = rMed.GetOutStream(); |
2753 | 0 | if ( pStream ) |
2754 | 0 | { |
2755 | 0 | weld::WaitObject aWait( GetActiveDialogParent() ); |
2756 | |
|
2757 | 0 | SCCOL nEndCol; |
2758 | 0 | SCROW nEndRow; |
2759 | 0 | m_pDocument->GetCellArea( 0, nEndCol, nEndRow ); |
2760 | 0 | ScRange aRange( 0,0,0, nEndCol,nEndRow,0 ); |
2761 | |
|
2762 | 0 | ScImportExport aImExport( *m_pDocument, aRange ); |
2763 | 0 | aImExport.SetFormulas( true ); |
2764 | 0 | bRet = aImExport.ExportStream( *pStream, rMed.GetBaseURL( true ), SotClipboardFormatId::SYLK ); |
2765 | 0 | } |
2766 | 0 | } |
2767 | 0 | else if (aFltName == pFilterHtml) |
2768 | 0 | { |
2769 | 0 | SvStream* pStream = rMed.GetOutStream(); |
2770 | 0 | if ( pStream ) |
2771 | 0 | { |
2772 | 0 | OUString sFilterOptions; |
2773 | |
|
2774 | 0 | if (const SfxStringItem* pOptionsItem = rMed.GetItemSet().GetItemIfSet(SID_FILE_FILTEROPTIONS)) |
2775 | 0 | sFilterOptions = pOptionsItem->GetValue(); |
2776 | |
|
2777 | 0 | weld::WaitObject aWait(GetActiveDialogParent()); |
2778 | 0 | ScImportExport aImExport(*m_pDocument); |
2779 | 0 | aImExport.SetStreamPath(rMed.GetName()); |
2780 | 0 | aImExport.SetFilterOptions(sFilterOptions); |
2781 | 0 | bRet = aImExport.ExportStream(*pStream, rMed.GetBaseURL(true), SotClipboardFormatId::HTML); |
2782 | 0 | if (bRet && !aImExport.GetNonConvertibleChars().isEmpty()) |
2783 | 0 | { |
2784 | 0 | SetError(ErrCodeMsg( |
2785 | 0 | SCWARN_EXPORT_NONCONVERTIBLE_CHARS, |
2786 | 0 | aImExport.GetNonConvertibleChars(), |
2787 | 0 | DialogMask::ButtonsOk | DialogMask::MessageInfo)); |
2788 | 0 | } |
2789 | 0 | } |
2790 | 0 | } |
2791 | 0 | else |
2792 | 0 | { |
2793 | 0 | if (GetErrorIgnoreWarning()) |
2794 | 0 | SetError(SCERR_IMPORT_NI); |
2795 | 0 | } |
2796 | | |
2797 | 0 | return bRet; |
2798 | 0 | } |
2799 | | |
2800 | | bool ScDocShell::DoSaveCompleted( SfxMedium * pNewStor, bool bRegisterRecent ) |
2801 | 0 | { |
2802 | 0 | bool bRet = SfxObjectShell::DoSaveCompleted( pNewStor, bRegisterRecent ); |
2803 | | |
2804 | | // SfxHintId::ScDocSaved for change ReadOnly -> Read/Write |
2805 | 0 | Broadcast( SfxHint( SfxHintId::ScDocSaved ) ); |
2806 | 0 | return bRet; |
2807 | 0 | } |
2808 | | |
2809 | | bool ScDocShell::QuerySlotExecutable( sal_uInt16 nSlotId ) |
2810 | 0 | { |
2811 | | // #i112634# ask VBA event handlers whether to save or print the document |
2812 | |
|
2813 | 0 | using namespace ::com::sun::star::script::vba; |
2814 | |
|
2815 | 0 | sal_Int32 nVbaEventId = VBAEventId::NO_EVENT; |
2816 | 0 | uno::Sequence< uno::Any > aArgs; |
2817 | 0 | switch( nSlotId ) |
2818 | 0 | { |
2819 | 0 | case SID_SAVEDOC: |
2820 | 0 | case SID_SAVEASDOC: |
2821 | 0 | nVbaEventId = VBAEventId::WORKBOOK_BEFORESAVE; |
2822 | 0 | aArgs = { uno::Any(nSlotId == SID_SAVEASDOC) }; |
2823 | 0 | break; |
2824 | 0 | case SID_PRINTDOC: |
2825 | 0 | case SID_PRINTDOCDIRECT: |
2826 | 0 | nVbaEventId = VBAEventId::WORKBOOK_BEFOREPRINT; |
2827 | 0 | break; |
2828 | 0 | } |
2829 | | |
2830 | 0 | bool bSlotExecutable = true; |
2831 | 0 | if( nVbaEventId != VBAEventId::NO_EVENT ) try |
2832 | 0 | { |
2833 | 0 | uno::Reference< XVBAEventProcessor > xEventProcessor( m_pDocument->GetVbaEventProcessor(), uno::UNO_SET_THROW ); |
2834 | 0 | xEventProcessor->processVbaEvent( nVbaEventId, aArgs ); |
2835 | 0 | } |
2836 | 0 | catch( util::VetoException& ) |
2837 | 0 | { |
2838 | 0 | bSlotExecutable = false; |
2839 | 0 | } |
2840 | 0 | catch( uno::Exception& ) |
2841 | 0 | { |
2842 | 0 | } |
2843 | 0 | return bSlotExecutable; |
2844 | 0 | } |
2845 | | |
2846 | | bool ScDocShell::PrepareClose( bool bUI ) |
2847 | 0 | { |
2848 | 0 | if (ScModule::get()->GetCurRefDlgId() > 0) |
2849 | 0 | { |
2850 | 0 | SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this ); |
2851 | 0 | if( pFrame ) |
2852 | 0 | { |
2853 | 0 | SfxViewShell* p = pFrame->GetViewShell(); |
2854 | 0 | ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( p ); |
2855 | 0 | if(pViewSh!=nullptr) |
2856 | 0 | { |
2857 | 0 | vcl::Window *pWin=pViewSh->GetWindow(); |
2858 | 0 | if(pWin!=nullptr) pWin->GrabFocus(); |
2859 | 0 | } |
2860 | 0 | } |
2861 | |
|
2862 | 0 | return false; |
2863 | 0 | } |
2864 | 0 | if ( m_pDocument->IsInLinkUpdate() || m_pDocument->IsInInterpreter() ) |
2865 | 0 | { |
2866 | 0 | ErrorMessage(STR_CLOSE_ERROR_LINK); |
2867 | 0 | return false; |
2868 | 0 | } |
2869 | | |
2870 | 0 | DoEnterHandler(); |
2871 | | |
2872 | | // start 'Workbook_BeforeClose' VBA event handler for possible veto |
2873 | 0 | if( !IsInPrepareClose() ) |
2874 | 0 | { |
2875 | 0 | try |
2876 | 0 | { |
2877 | 0 | uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( m_pDocument->GetVbaEventProcessor(), uno::UNO_SET_THROW ); |
2878 | 0 | uno::Sequence< uno::Any > aArgs; |
2879 | 0 | xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_BEFORECLOSE, aArgs ); |
2880 | 0 | } |
2881 | 0 | catch( util::VetoException& ) |
2882 | 0 | { |
2883 | | // if event processor throws VetoException, macro has vetoed close |
2884 | 0 | return false; |
2885 | 0 | } |
2886 | 0 | catch( uno::Exception& ) |
2887 | 0 | { |
2888 | 0 | } |
2889 | 0 | } |
2890 | | // end handler code |
2891 | | |
2892 | 0 | bool bRet = SfxObjectShell::PrepareClose( bUI ); |
2893 | 0 | if (bRet) // true == close |
2894 | 0 | m_pDocument->EnableIdle(false); // Do not mess around with it anymore! |
2895 | |
|
2896 | 0 | return bRet; |
2897 | 0 | } |
2898 | | |
2899 | | OUString ScDocShell::GetOwnFilterName() |
2900 | 2.00k | { |
2901 | 2.00k | return pFilterSc50; |
2902 | 2.00k | } |
2903 | | |
2904 | | const OUString & ScDocShell::GetHtmlFilterName() |
2905 | 0 | { |
2906 | 0 | return pFilterHtml; |
2907 | 0 | } |
2908 | | |
2909 | | const OUString & ScDocShell::GetWebQueryFilterName() |
2910 | 0 | { |
2911 | 0 | return pFilterHtmlWebQ; |
2912 | 0 | } |
2913 | | |
2914 | | const OUString & ScDocShell::GetAsciiFilterName() |
2915 | 0 | { |
2916 | 0 | return SC_TEXT_CSV_FILTER_NAME; |
2917 | 0 | } |
2918 | | |
2919 | | const OUString & ScDocShell::GetLotusFilterName() |
2920 | 0 | { |
2921 | 0 | return pFilterLotus; |
2922 | 0 | } |
2923 | | |
2924 | | const OUString & ScDocShell::GetDBaseFilterName() |
2925 | 0 | { |
2926 | 0 | return pFilterDBase; |
2927 | 0 | } |
2928 | | |
2929 | | const OUString & ScDocShell::GetDifFilterName() |
2930 | 0 | { |
2931 | 0 | return pFilterDif; |
2932 | 0 | } |
2933 | | |
2934 | | bool ScDocShell::HasAutomaticTableName( std::u16string_view rFilter ) |
2935 | 0 | { |
2936 | | // sal_True for those filters that keep the default table name |
2937 | | // (which is language specific) |
2938 | |
|
2939 | 0 | return rFilter == SC_TEXT_CSV_FILTER_NAME |
2940 | 0 | || rFilter == pFilterLotus |
2941 | 0 | || rFilter == pFilterExcel4 |
2942 | 0 | || rFilter == pFilterEx4Temp |
2943 | 0 | || rFilter == pFilterDBase |
2944 | 0 | || rFilter == pFilterDif |
2945 | 0 | || rFilter == pFilterSylk |
2946 | 0 | || rFilter == pFilterHtml |
2947 | 0 | || rFilter == pFilterRtf; |
2948 | 0 | } |
2949 | | |
2950 | | std::unique_ptr<ScDocFunc> ScDocShell::CreateDocFunc() |
2951 | 77.1k | { |
2952 | 77.1k | return std::make_unique<ScDocFuncDirect>( *this ); |
2953 | 77.1k | } |
2954 | | |
2955 | | ScDocShell::ScDocShell( const SfxModelFlags i_nSfxCreationFlags, const std::shared_ptr<ScDocument>& pDoc ) : |
2956 | 77.1k | SfxObjectShell( i_nSfxCreationFlags ), |
2957 | 77.1k | m_pDocument ( pDoc ? pDoc : std::make_shared<ScDocument>( SCDOCMODE_DOCUMENT, this )), |
2958 | 77.1k | m_aDdeTextFmt(u"TEXT"_ustr), |
2959 | 77.1k | m_nPrtToScreenFactor( 1.0 ), |
2960 | 77.1k | m_pImpl ( new DocShell_Impl ), |
2961 | 77.1k | m_bHeaderOn ( true ), |
2962 | 77.1k | m_bFooterOn ( true ), |
2963 | 77.1k | m_bIsEmpty ( true ), |
2964 | 77.1k | m_bIsInUndo ( false ), |
2965 | 77.1k | m_bDocumentModifiedPending( false ), |
2966 | 77.1k | m_bUpdateEnabled ( true ), |
2967 | 77.1k | m_bAreasChangedNeedBroadcast( false ), |
2968 | 77.1k | m_nDocumentLock ( 0 ), |
2969 | 77.1k | m_nCanUpdate (css::document::UpdateDocMode::ACCORDING_TO_CONFIG) |
2970 | 77.1k | { |
2971 | 77.1k | SetPool(&ScModule::get()->GetPool()); |
2972 | | |
2973 | 77.1k | m_bIsInplace = (GetCreateMode() == SfxObjectCreateMode::EMBEDDED); |
2974 | | // Will be reset if not in place |
2975 | | |
2976 | 77.1k | m_pDocFunc = CreateDocFunc(); |
2977 | | |
2978 | | // SetBaseModel needs exception handling |
2979 | 77.1k | ScModelObj::CreateAndSet( this ); |
2980 | | |
2981 | 77.1k | StartListening(*this); |
2982 | 77.1k | SfxStyleSheetPool* pStlPool = m_pDocument->GetStyleSheetPool(); |
2983 | 77.1k | if (pStlPool) |
2984 | 77.1k | StartListening(*pStlPool); |
2985 | | |
2986 | 77.1k | m_pDocument->GetDBCollection()->SetRefreshHandler( |
2987 | 77.1k | LINK( this, ScDocShell, RefreshDBDataHdl ) ); |
2988 | | |
2989 | | // InitItems and CalcOutputFactor are called now in Load/ConvertFrom/InitNew |
2990 | 77.1k | } |
2991 | | |
2992 | | ScDocShell::~ScDocShell() |
2993 | 77.0k | { |
2994 | 77.0k | ResetDrawObjectShell(); // If the Drawing Layer still tries to access it, access it |
2995 | | |
2996 | 77.0k | SfxStyleSheetPool* pStlPool = m_pDocument->GetStyleSheetPool(); |
2997 | 77.0k | if (pStlPool) |
2998 | 77.0k | EndListening(*pStlPool); |
2999 | 77.0k | EndListening(*this); |
3000 | | |
3001 | 77.0k | m_pAutoStyleList.reset(); |
3002 | | |
3003 | 77.0k | SfxApplication *pSfxApp = SfxGetpApp(); |
3004 | 77.0k | if ( pSfxApp->GetDdeService() ) // Delete DDE for Document |
3005 | 0 | pSfxApp->RemoveDdeTopic( this ); |
3006 | | |
3007 | 77.0k | m_pDocFunc.reset(); |
3008 | 77.0k | delete m_pDocument->mpUndoManager; |
3009 | 77.0k | m_pDocument->mpUndoManager = nullptr; |
3010 | 77.0k | m_pImpl.reset(); |
3011 | | |
3012 | 77.0k | m_pPaintLockData.reset(); |
3013 | | |
3014 | 77.0k | m_pSheetSaveData.reset(); |
3015 | 77.0k | m_pFormatSaveData.reset(); |
3016 | 77.0k | m_pOldAutoDBRange.reset(); |
3017 | | |
3018 | 77.0k | if (m_pModificator) |
3019 | 30.7k | { |
3020 | 30.7k | OSL_FAIL("The Modificator should not exist"); |
3021 | 30.7k | m_pModificator.reset(); |
3022 | 30.7k | } |
3023 | 77.0k | } |
3024 | | |
3025 | | SfxUndoManager* ScDocShell::GetUndoManager() |
3026 | 70 | { |
3027 | 70 | return m_pDocument->GetUndoManager(); |
3028 | 70 | } |
3029 | | |
3030 | | void ScDocShell::SetModified( bool bModified ) |
3031 | 108k | { |
3032 | 108k | if ( SfxObjectShell::IsEnableSetModified() ) |
3033 | 108k | { |
3034 | 108k | SfxObjectShell::SetModified( bModified ); |
3035 | 108k | Broadcast( SfxHint( SfxHintId::DocChanged ) ); |
3036 | 108k | } |
3037 | 108k | } |
3038 | | |
3039 | | void ScDocShell::SetDocumentModified() |
3040 | 285k | { |
3041 | | // BroadcastUno must also happen right away with pPaintLockData |
3042 | | // FIXME: Also for SetDrawModified, if Drawing is connected |
3043 | | // FIXME: Then own Hint? |
3044 | | |
3045 | 285k | if ( m_pPaintLockData ) |
3046 | 268k | { |
3047 | | // #i115009# broadcast BCA_BRDCST_ALWAYS, so a component can read recalculated results |
3048 | | // of RecalcModeAlways formulas (like OFFSET) after modifying cells |
3049 | 268k | m_pDocument->Broadcast(ScHint(SfxHintId::ScDataChanged, BCA_BRDCST_ALWAYS)); |
3050 | 268k | m_pDocument->InvalidateTableArea(); // #i105279# needed here |
3051 | 268k | m_pDocument->BroadcastUno( SfxHint( SfxHintId::DataChanged ) ); |
3052 | | |
3053 | 268k | m_pPaintLockData->SetModified(); // Later on ... |
3054 | 268k | return; |
3055 | 268k | } |
3056 | | |
3057 | 17.7k | SetDrawModified(); |
3058 | | |
3059 | 17.7k | if ( m_pDocument->IsAutoCalcShellDisabled() ) |
3060 | 0 | SetDocumentModifiedPending( true ); |
3061 | 17.7k | else |
3062 | 17.7k | { |
3063 | 17.7k | SetDocumentModifiedPending( false ); |
3064 | 17.7k | m_pDocument->InvalidateStyleSheetUsage(); |
3065 | 17.7k | m_pDocument->InvalidateTableArea(); |
3066 | 17.7k | m_pDocument->InvalidateLastTableOpParams(); |
3067 | 17.7k | m_pDocument->Broadcast(ScHint(SfxHintId::ScDataChanged, BCA_BRDCST_ALWAYS)); |
3068 | 17.7k | if ( m_pDocument->IsForcedFormulaPending() && m_pDocument->GetAutoCalc() ) |
3069 | 0 | m_pDocument->CalcFormulaTree( true ); |
3070 | 17.7k | m_pDocument->RefreshDirtyTableColumnNames(); |
3071 | 17.7k | PostDataChanged(); |
3072 | | |
3073 | | // Detective AutoUpdate: |
3074 | | // Update if formulas were modified (DetectiveDirty) or the list contains |
3075 | | // "Trace Error" entries (Trace Error can look completely different |
3076 | | // after changes to non-formula cells). |
3077 | | |
3078 | 17.7k | ScDetOpList* pList = m_pDocument->GetDetOpList(); |
3079 | 17.7k | if ( pList && ( m_pDocument->IsDetectiveDirty() || pList->HasAddError() ) && |
3080 | 17.7k | pList->Count() && !IsInUndo() && ScModule::get()->GetAppOptions().GetDetectiveAuto() ) |
3081 | 0 | { |
3082 | 0 | GetDocFunc().DetectiveRefresh(true); // sal_True = caused by automatic update |
3083 | 0 | } |
3084 | 17.7k | m_pDocument->SetDetectiveDirty(false); // always reset, also if not refreshed |
3085 | 17.7k | } |
3086 | | |
3087 | 17.7k | if (m_bAreasChangedNeedBroadcast) |
3088 | 0 | { |
3089 | 0 | m_bAreasChangedNeedBroadcast = false; |
3090 | 0 | SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged)); |
3091 | 0 | } |
3092 | | |
3093 | | // notify UNO objects after BCA_BRDCST_ALWAYS etc. |
3094 | 17.7k | m_pDocument->BroadcastUno( SfxHint( SfxHintId::DataChanged ) ); |
3095 | 17.7k | } |
3096 | | |
3097 | | /** |
3098 | | * SetDrawModified - without Formula update |
3099 | | * |
3100 | | * Drawing also needs to be updated for the normal SetDocumentModified |
3101 | | * e.g.: when deleting tables etc. |
3102 | | */ |
3103 | | void ScDocShell::SetDrawModified() |
3104 | 17.7k | { |
3105 | 17.7k | bool bUpdate = !IsModified(); |
3106 | | |
3107 | 17.7k | SetModified(); |
3108 | | |
3109 | 17.7k | SfxBindings* pBindings = GetViewBindings(); |
3110 | 17.7k | if (bUpdate && pBindings) |
3111 | 0 | { |
3112 | 0 | pBindings->Invalidate( SID_SAVEDOC ); |
3113 | 0 | pBindings->Invalidate( SID_DOC_MODIFIED ); |
3114 | 0 | } |
3115 | | |
3116 | 17.7k | if (pBindings) |
3117 | 0 | { |
3118 | | // #i105960# Undo etc used to be volatile. |
3119 | | // They always have to be invalidated, including drawing layer or row height changes |
3120 | | // (but not while pPaintLockData is set). |
3121 | 0 | pBindings->Invalidate( SID_UNDO ); |
3122 | 0 | pBindings->Invalidate( SID_REDO ); |
3123 | 0 | pBindings->Invalidate( SID_REPEAT ); |
3124 | 0 | } |
3125 | | |
3126 | 17.7k | if ( m_pDocument->IsChartListenerCollectionNeedsUpdate() ) |
3127 | 5.27k | { |
3128 | 5.27k | m_pDocument->UpdateChartListenerCollection(); |
3129 | 5.27k | SfxGetpApp()->Broadcast(SfxHint( SfxHintId::ScDrawChanged )); // Navigator |
3130 | 5.27k | } |
3131 | 17.7k | ScModule::get()->AnythingChanged(); |
3132 | 17.7k | } |
3133 | | |
3134 | | void ScDocShell::SetInUndo(bool bSet) |
3135 | 0 | { |
3136 | 0 | m_bIsInUndo = bSet; |
3137 | 0 | } |
3138 | | |
3139 | | void ScDocShell::GetDocStat( ScDocStat& rDocStat ) |
3140 | 0 | { |
3141 | 0 | SfxPrinter* pPrinter = GetPrinter(); |
3142 | |
|
3143 | 0 | m_pDocument->GetDocStat( rDocStat ); |
3144 | 0 | rDocStat.nPageCount = 0; |
3145 | |
|
3146 | 0 | if ( pPrinter ) |
3147 | 0 | for ( SCTAB i=0; i<rDocStat.nTableCount; i++ ) |
3148 | 0 | rDocStat.nPageCount = sal::static_int_cast<sal_uInt16>( rDocStat.nPageCount + |
3149 | 0 | static_cast<sal_uInt16>(ScPrintFunc( *this, pPrinter, i ).GetTotalPages()) ); |
3150 | 0 | } |
3151 | | |
3152 | | std::shared_ptr<SfxDocumentInfoDialog> ScDocShell::CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet &rSet) |
3153 | 0 | { |
3154 | 0 | std::shared_ptr<SfxDocumentInfoDialog> xDlg = std::make_shared<SfxDocumentInfoDialog>(pParent, rSet); |
3155 | 0 | ScDocShell* pDocSh = dynamic_cast< ScDocShell *>( SfxObjectShell::Current() ); |
3156 | | |
3157 | | // Only for statistics, if this Doc is shown; not from the Doc Manager |
3158 | 0 | if( pDocSh == this ) |
3159 | 0 | { |
3160 | 0 | ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); |
3161 | 0 | ::CreateTabPage ScDocStatPageCreate = pFact->GetTabPageCreatorFunc(SID_SC_TP_STAT); |
3162 | 0 | OSL_ENSURE(ScDocStatPageCreate, "Tabpage create fail!"); |
3163 | 0 | xDlg->AddFontTabPage(); |
3164 | 0 | xDlg->AddTabPage(u"calcstats"_ustr, ScResId(STR_DOC_STAT), ScDocStatPageCreate); |
3165 | 0 | } |
3166 | 0 | return xDlg; |
3167 | 0 | } |
3168 | | |
3169 | | weld::Window* ScDocShell::GetActiveDialogParent() |
3170 | 15.2k | { |
3171 | 15.2k | ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); |
3172 | 15.2k | if ( pViewSh ) |
3173 | 0 | return pViewSh->GetDialogParent(); |
3174 | 15.2k | return Application::GetDefDialogParent(); |
3175 | 15.2k | } |
3176 | | |
3177 | | ScSheetSaveData* ScDocShell::GetSheetSaveData() |
3178 | 177k | { |
3179 | 177k | if (!m_pSheetSaveData) |
3180 | 44.6k | m_pSheetSaveData.reset( new ScSheetSaveData ); |
3181 | | |
3182 | 177k | return m_pSheetSaveData.get(); |
3183 | 177k | } |
3184 | | |
3185 | | ScFormatSaveData* ScDocShell::GetFormatSaveData() |
3186 | 1.00k | { |
3187 | 1.00k | if (!m_pFormatSaveData) |
3188 | 612 | m_pFormatSaveData.reset( new ScFormatSaveData ); |
3189 | | |
3190 | 1.00k | return m_pFormatSaveData.get(); |
3191 | 1.00k | } |
3192 | | |
3193 | | namespace { |
3194 | | |
3195 | | void removeKeysIfExists(const Reference<ui::XAcceleratorConfiguration>& xScAccel, const vector<const awt::KeyEvent*>& rKeys) |
3196 | 0 | { |
3197 | 0 | for (const awt::KeyEvent* p : rKeys) |
3198 | 0 | { |
3199 | 0 | if (!p) |
3200 | 0 | continue; |
3201 | | |
3202 | 0 | try |
3203 | 0 | { |
3204 | 0 | xScAccel->removeKeyEvent(*p); |
3205 | 0 | } |
3206 | 0 | catch (const container::NoSuchElementException&) {} |
3207 | 0 | } |
3208 | 0 | } |
3209 | | |
3210 | | } |
3211 | | |
3212 | | void ScDocShell::ResetKeyBindings( ScOptionsUtil::KeyBindingType eType ) |
3213 | 0 | { |
3214 | 0 | using namespace ::com::sun::star::ui; |
3215 | |
|
3216 | 0 | const Reference<uno::XComponentContext>& xContext = ::comphelper::getProcessComponentContext(); |
3217 | 0 | if (!xContext.is()) |
3218 | 0 | return; |
3219 | | |
3220 | 0 | Reference<XModuleUIConfigurationManagerSupplier> xModuleCfgSupplier( |
3221 | 0 | theModuleUIConfigurationManagerSupplier::get(xContext) ); |
3222 | | |
3223 | | // Grab the Calc configuration. |
3224 | 0 | Reference<XUIConfigurationManager> xConfigMgr = |
3225 | 0 | xModuleCfgSupplier->getUIConfigurationManager( |
3226 | 0 | u"com.sun.star.sheet.SpreadsheetDocument"_ustr); |
3227 | |
|
3228 | 0 | if (!xConfigMgr.is()) |
3229 | 0 | return; |
3230 | | |
3231 | | // shortcut manager |
3232 | 0 | Reference<XAcceleratorConfiguration> xScAccel = xConfigMgr->getShortCutManager(); |
3233 | |
|
3234 | 0 | if (!xScAccel.is()) |
3235 | 0 | return; |
3236 | | |
3237 | 0 | vector<const awt::KeyEvent*> aKeys; |
3238 | 0 | aKeys.reserve(9); |
3239 | | |
3240 | | // Backspace key |
3241 | 0 | awt::KeyEvent aBackspace; |
3242 | 0 | aBackspace.KeyCode = awt::Key::BACKSPACE; |
3243 | 0 | aBackspace.Modifiers = 0; |
3244 | 0 | aKeys.push_back(&aBackspace); |
3245 | | |
3246 | | // Delete key |
3247 | 0 | awt::KeyEvent aDelete; |
3248 | 0 | aDelete.KeyCode = awt::Key::DELETE; |
3249 | 0 | aDelete.Modifiers = 0; |
3250 | 0 | aKeys.push_back(&aDelete); |
3251 | | |
3252 | | // Ctrl-D |
3253 | 0 | awt::KeyEvent aCtrlD; |
3254 | 0 | aCtrlD.KeyCode = awt::Key::D; |
3255 | 0 | aCtrlD.Modifiers = awt::KeyModifier::MOD1; |
3256 | 0 | aKeys.push_back(&aCtrlD); |
3257 | | |
3258 | | // Alt-Down |
3259 | 0 | awt::KeyEvent aAltDown; |
3260 | 0 | aAltDown.KeyCode = awt::Key::DOWN; |
3261 | 0 | aAltDown.Modifiers = awt::KeyModifier::MOD2; |
3262 | 0 | aKeys.push_back(&aAltDown); |
3263 | | |
3264 | | // Ctrl-Space |
3265 | 0 | awt::KeyEvent aCtrlSpace; |
3266 | 0 | aCtrlSpace.KeyCode = awt::Key::SPACE; |
3267 | 0 | aCtrlSpace.Modifiers = awt::KeyModifier::MOD1; |
3268 | 0 | aKeys.push_back(&aCtrlSpace); |
3269 | | |
3270 | | // Ctrl-Shift-Space |
3271 | 0 | awt::KeyEvent aCtrlShiftSpace; |
3272 | 0 | aCtrlShiftSpace.KeyCode = awt::Key::SPACE; |
3273 | 0 | aCtrlShiftSpace.Modifiers = awt::KeyModifier::MOD1 | awt::KeyModifier::SHIFT; |
3274 | 0 | aKeys.push_back(&aCtrlShiftSpace); |
3275 | | |
3276 | | // F4 |
3277 | 0 | awt::KeyEvent aF4; |
3278 | 0 | aF4.KeyCode = awt::Key::F4; |
3279 | 0 | aF4.Modifiers = 0; |
3280 | 0 | aKeys.push_back(&aF4); |
3281 | | |
3282 | | // CTRL+SHIFT+F4 |
3283 | 0 | awt::KeyEvent aCtrlShiftF4; |
3284 | 0 | aCtrlShiftF4.KeyCode = awt::Key::F4; |
3285 | 0 | aCtrlShiftF4.Modifiers = awt::KeyModifier::MOD1 | awt::KeyModifier::SHIFT; |
3286 | 0 | aKeys.push_back(&aCtrlShiftF4); |
3287 | | |
3288 | | // SHIFT+F4 |
3289 | 0 | awt::KeyEvent aShiftF4; |
3290 | 0 | aShiftF4.KeyCode = awt::Key::F4; |
3291 | 0 | aShiftF4.Modifiers = awt::KeyModifier::SHIFT; |
3292 | 0 | aKeys.push_back(&aShiftF4); |
3293 | | |
3294 | | // Remove all involved keys first, because swapping commands don't work |
3295 | | // well without doing this. |
3296 | 0 | removeKeysIfExists(xScAccel, aKeys); |
3297 | 0 | xScAccel->store(); |
3298 | |
|
3299 | 0 | switch (eType) |
3300 | 0 | { |
3301 | 0 | case ScOptionsUtil::KEY_DEFAULT: |
3302 | 0 | xScAccel->setKeyEvent(aDelete, u".uno:ClearContents"_ustr); |
3303 | 0 | xScAccel->setKeyEvent(aBackspace, u".uno:Delete"_ustr); |
3304 | 0 | xScAccel->setKeyEvent(aCtrlD, u".uno:FillDown"_ustr); |
3305 | 0 | xScAccel->setKeyEvent(aAltDown, u".uno:DataSelect"_ustr); |
3306 | 0 | xScAccel->setKeyEvent(aCtrlSpace, u".uno:SelectColumn"_ustr); |
3307 | 0 | xScAccel->setKeyEvent(aCtrlShiftSpace, u".uno:SelectAll"_ustr); |
3308 | 0 | xScAccel->setKeyEvent(aF4, u".uno:ToggleRelative"_ustr); |
3309 | 0 | xScAccel->setKeyEvent(aCtrlShiftF4, u".uno:ViewDataSourceBrowser"_ustr); |
3310 | 0 | break; |
3311 | 0 | case ScOptionsUtil::KEY_OOO_LEGACY: |
3312 | 0 | xScAccel->setKeyEvent(aDelete, u".uno:Delete"_ustr); |
3313 | 0 | xScAccel->setKeyEvent(aBackspace, u".uno:ClearContents"_ustr); |
3314 | 0 | xScAccel->setKeyEvent(aCtrlD, u".uno:DataSelect"_ustr); |
3315 | 0 | xScAccel->setKeyEvent(aCtrlShiftSpace, u".uno:SelectColumn"_ustr); |
3316 | 0 | xScAccel->setKeyEvent(aF4, u".uno:ViewDataSourceBrowser"_ustr); |
3317 | 0 | xScAccel->setKeyEvent(aShiftF4, u".uno:ToggleRelative"_ustr); |
3318 | 0 | break; |
3319 | 0 | default: |
3320 | 0 | ; |
3321 | 0 | } |
3322 | | |
3323 | 0 | xScAccel->store(); |
3324 | 0 | } |
3325 | | |
3326 | | void ScDocShell::UseSheetSaveEntries() |
3327 | 0 | { |
3328 | 0 | if (!m_pSheetSaveData) |
3329 | 0 | return; |
3330 | | |
3331 | 0 | m_pSheetSaveData->UseSaveEntries(); // use positions from saved file for next saving |
3332 | |
|
3333 | 0 | bool bHasEntries = false; |
3334 | 0 | SCTAB nTabCount = m_pDocument->GetTableCount(); |
3335 | 0 | SCTAB nTab; |
3336 | 0 | for (nTab = 0; nTab < nTabCount; ++nTab) |
3337 | 0 | if (m_pSheetSaveData->HasStreamPos(nTab)) |
3338 | 0 | bHasEntries = true; |
3339 | |
|
3340 | 0 | if (!bHasEntries) |
3341 | 0 | { |
3342 | | // if no positions were set (for example, export to other format), |
3343 | | // reset all "valid" flags |
3344 | 0 | for (nTab = 0; nTab < nTabCount; ++nTab) |
3345 | 0 | m_pDocument->SetStreamValid(nTab, false); |
3346 | 0 | } |
3347 | 0 | } |
3348 | | |
3349 | | // --- ScDocShellModificator ------------------------------------------ |
3350 | | |
3351 | | ScDocShellModificator::ScDocShellModificator( ScDocShell& rDS ) |
3352 | | : |
3353 | 738k | rDocShell( rDS ), |
3354 | 738k | mpProtector(new ScRefreshTimerProtector(rDS.GetDocument().GetRefreshTimerControlAddress())) |
3355 | 738k | { |
3356 | 738k | ScDocument& rDoc = rDocShell.GetDocument(); |
3357 | 738k | bAutoCalcShellDisabled = rDoc.IsAutoCalcShellDisabled(); |
3358 | 738k | bIdleEnabled = rDoc.IsIdleEnabled(); |
3359 | 738k | rDoc.SetAutoCalcShellDisabled( true ); |
3360 | 738k | rDoc.EnableIdle(false); |
3361 | 738k | } |
3362 | | |
3363 | | void ScDocShellModificator::ImplDestroy() |
3364 | 738k | { |
3365 | 738k | ScDocument& rDoc = rDocShell.GetDocument(); |
3366 | 738k | rDoc.SetAutoCalcShellDisabled( bAutoCalcShellDisabled ); |
3367 | 738k | if ( !bAutoCalcShellDisabled && rDocShell.IsDocumentModifiedPending() ) |
3368 | 0 | rDocShell.SetDocumentModified(); // last one shuts off the lights |
3369 | 738k | rDoc.EnableIdle(bIdleEnabled); |
3370 | 738k | } |
3371 | | |
3372 | | ScDocShellModificator::~ScDocShellModificator() |
3373 | 738k | { |
3374 | 738k | suppress_fun_call_w_exception(ImplDestroy()); |
3375 | 738k | } |
3376 | | |
3377 | | void ScDocShellModificator::SetDocumentModified() |
3378 | 563k | { |
3379 | 563k | ScDocument& rDoc = rDocShell.GetDocument(); |
3380 | 563k | rDoc.PrepareFormulaCalc(); |
3381 | 563k | if ( !rDoc.IsImportingXML() ) |
3382 | 227k | { |
3383 | | // temporarily restore AutoCalcShellDisabled |
3384 | 227k | bool bDisabled = rDoc.IsAutoCalcShellDisabled(); |
3385 | 227k | rDoc.SetAutoCalcShellDisabled( bAutoCalcShellDisabled ); |
3386 | 227k | rDocShell.SetDocumentModified(); |
3387 | 227k | rDoc.SetAutoCalcShellDisabled( bDisabled ); |
3388 | 227k | } |
3389 | 336k | else |
3390 | 336k | { |
3391 | | // uno broadcast is necessary for api to work |
3392 | | // -> must also be done during xml import |
3393 | 336k | rDoc.BroadcastUno( SfxHint( SfxHintId::DataChanged ) ); |
3394 | 336k | } |
3395 | 563k | } |
3396 | | |
3397 | | bool ScDocShell::IsChangeRecording(SfxViewShell* /*pViewShell*/, bool /*bRecordAllViews*/) const |
3398 | 0 | { |
3399 | 0 | ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack(); |
3400 | 0 | return pChangeTrack != nullptr; |
3401 | 0 | } |
3402 | | |
3403 | | bool ScDocShell::HasChangeRecordProtection() const |
3404 | 0 | { |
3405 | 0 | bool bRes = false; |
3406 | 0 | ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack(); |
3407 | 0 | if (pChangeTrack) |
3408 | 0 | bRes = pChangeTrack->IsProtected(); |
3409 | 0 | return bRes; |
3410 | 0 | } |
3411 | | |
3412 | | void ScDocShell::SetChangeRecording( bool bActivate, bool /*bLockAllViews*/, SfxRedlineRecordingMode /*eRedlineRecordingMode*/) |
3413 | 0 | { |
3414 | 0 | bool bOldChangeRecording = IsChangeRecording(); |
3415 | |
|
3416 | 0 | if (bActivate) |
3417 | 0 | { |
3418 | 0 | m_pDocument->StartChangeTracking(); |
3419 | 0 | ScChangeViewSettings aChangeViewSet; |
3420 | 0 | aChangeViewSet.SetShowChanges(true); |
3421 | 0 | m_pDocument->SetChangeViewSettings(aChangeViewSet); |
3422 | 0 | } |
3423 | 0 | else |
3424 | 0 | { |
3425 | 0 | m_pDocument->EndChangeTracking(); |
3426 | 0 | PostPaintGridAll(); |
3427 | 0 | } |
3428 | |
|
3429 | 0 | if (bOldChangeRecording != IsChangeRecording()) |
3430 | 0 | { |
3431 | 0 | UpdateAcceptChangesDialog(); |
3432 | | // invalidate slots |
3433 | 0 | SfxBindings* pBindings = GetViewBindings(); |
3434 | 0 | if (pBindings) |
3435 | 0 | pBindings->InvalidateAll(false); |
3436 | 0 | } |
3437 | 0 | } |
3438 | | |
3439 | | void ScDocShell::SetProtectionPassword( const OUString &rNewPassword ) |
3440 | 0 | { |
3441 | 0 | ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack(); |
3442 | 0 | if (!pChangeTrack) |
3443 | 0 | return; |
3444 | | |
3445 | 0 | bool bProtected = pChangeTrack->IsProtected(); |
3446 | |
|
3447 | 0 | if (!rNewPassword.isEmpty()) |
3448 | 0 | { |
3449 | | // when password protection is applied change tracking must always be active |
3450 | 0 | SetChangeRecording( true ); |
3451 | |
|
3452 | 0 | css::uno::Sequence< sal_Int8 > aProtectionHash; |
3453 | 0 | SvPasswordHelper::GetHashPassword( aProtectionHash, rNewPassword ); |
3454 | 0 | pChangeTrack->SetProtection( aProtectionHash ); |
3455 | 0 | } |
3456 | 0 | else |
3457 | 0 | { |
3458 | 0 | pChangeTrack->SetProtection( css::uno::Sequence< sal_Int8 >() ); |
3459 | 0 | } |
3460 | |
|
3461 | 0 | if ( bProtected != pChangeTrack->IsProtected() ) |
3462 | 0 | { |
3463 | 0 | UpdateAcceptChangesDialog(); |
3464 | 0 | SetDocumentModified(); |
3465 | 0 | } |
3466 | 0 | } |
3467 | | |
3468 | | bool ScDocShell::GetProtectionHash( /*out*/ css::uno::Sequence< sal_Int8 > &rPasswordHash ) |
3469 | 0 | { |
3470 | 0 | bool bRes = false; |
3471 | 0 | ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack(); |
3472 | 0 | if (pChangeTrack && pChangeTrack->IsProtected()) |
3473 | 0 | { |
3474 | 0 | rPasswordHash = pChangeTrack->GetProtection(); |
3475 | 0 | bRes = true; |
3476 | 0 | } |
3477 | 0 | return bRes; |
3478 | 0 | } |
3479 | | |
3480 | | void ScDocShell::RegisterAutomationWorkbookObject(css::uno::Reference< ooo::vba::excel::XWorkbook > const& xWorkbook) |
3481 | 0 | { |
3482 | 0 | mxAutomationWorkbookObject = xWorkbook; |
3483 | 0 | } |
3484 | | |
3485 | | extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportSLK(SvStream &rStream) |
3486 | 24.9k | { |
3487 | 24.9k | ScDLL::Init(); |
3488 | 24.9k | ScDocument aDocument; |
3489 | 24.9k | ScDocOptions aDocOpt = aDocument.GetDocOptions(); |
3490 | 24.9k | aDocOpt.SetLookUpColRowNames(false); |
3491 | 24.9k | aDocument.SetDocOptions(aDocOpt); |
3492 | 24.9k | aDocument.MakeTable(0); |
3493 | 24.9k | aDocument.EnableExecuteLink(false); |
3494 | 24.9k | aDocument.SetInsertingFromOtherDoc(true); |
3495 | 24.9k | aDocument.SetImportingXML(true); |
3496 | | |
3497 | 24.9k | ScImportExport aImpEx(aDocument); |
3498 | 24.9k | return aImpEx.ImportStream(rStream, OUString(), SotClipboardFormatId::SYLK); |
3499 | 24.9k | } |
3500 | | |
3501 | | extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportCalcHTML(SvStream &rStream) |
3502 | 25.0k | { |
3503 | 25.0k | ScDLL::Init(); |
3504 | 25.0k | ScDocument aDocument; |
3505 | 25.0k | ScDocOptions aDocOpt = aDocument.GetDocOptions(); |
3506 | 25.0k | aDocOpt.SetLookUpColRowNames(false); |
3507 | 25.0k | aDocument.SetDocOptions(aDocOpt); |
3508 | 25.0k | aDocument.MakeTable(0); |
3509 | 25.0k | aDocument.EnableExecuteLink(false); |
3510 | 25.0k | aDocument.SetInsertingFromOtherDoc(true); |
3511 | 25.0k | aDocument.SetImportingXML(true); |
3512 | | |
3513 | 25.0k | ScImportExport aImpEx(aDocument); |
3514 | 25.0k | return aImpEx.ImportStream(rStream, OUString(), SotClipboardFormatId::HTML); |
3515 | 25.0k | } |
3516 | | |
3517 | | extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportDBF(SvStream &rStream) |
3518 | 9.91k | { |
3519 | 9.91k | ScDLL::Init(); |
3520 | | |
3521 | | // we need a real file for this filter |
3522 | | |
3523 | | // put it in an empty dir |
3524 | 9.91k | utl::TempFileNamed aTmpDir(nullptr, true); |
3525 | 9.91k | aTmpDir.EnableKillingFile(); |
3526 | 9.91k | OUString sTmpDir = aTmpDir.GetURL(); |
3527 | | |
3528 | 9.91k | utl::TempFileNamed aTempInput(u"", true, u".dbf", &sTmpDir); |
3529 | 9.91k | aTempInput.EnableKillingFile(); |
3530 | | |
3531 | 9.91k | SvStream* pInputStream = aTempInput.GetStream(StreamMode::WRITE); |
3532 | 9.91k | sal_uInt8 aBuffer[8192]; |
3533 | 21.4k | while (auto nRead = rStream.ReadBytes(aBuffer, SAL_N_ELEMENTS(aBuffer))) |
3534 | 11.4k | pInputStream->WriteBytes(aBuffer, nRead); |
3535 | 9.91k | aTempInput.CloseStream(); |
3536 | | |
3537 | 9.91k | SfxMedium aMedium(aTempInput.GetURL(), StreamMode::STD_READWRITE); |
3538 | | |
3539 | 9.91k | ScDocShellRef xDocShell = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT | |
3540 | 9.91k | SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS | |
3541 | 9.91k | SfxModelFlags::DISABLE_DOCUMENT_RECOVERY); |
3542 | | |
3543 | 9.91k | xDocShell->DoInitNew(); |
3544 | | |
3545 | 9.91k | ScDocument& rDoc = xDocShell->GetDocument(); |
3546 | | |
3547 | 9.91k | ScDocOptions aDocOpt = rDoc.GetDocOptions(); |
3548 | 9.91k | aDocOpt.SetLookUpColRowNames(false); |
3549 | 9.91k | rDoc.SetDocOptions(aDocOpt); |
3550 | 9.91k | rDoc.MakeTable(0); |
3551 | 9.91k | rDoc.EnableExecuteLink(false); |
3552 | 9.91k | rDoc.SetInsertingFromOtherDoc(true); |
3553 | | |
3554 | 9.91k | ScDocRowHeightUpdater::TabRanges aRecalcRanges(0, rDoc.MaxRow()); |
3555 | 9.91k | std::map<SCCOL, ScColWidthParam> aColWidthParam; |
3556 | 9.91k | ErrCode eError = xDocShell->DBaseImport(aMedium.GetPhysicalName(), RTL_TEXTENCODING_IBM_850, aColWidthParam, aRecalcRanges.maRanges); |
3557 | | |
3558 | 9.91k | xDocShell->DoClose(); |
3559 | 9.91k | xDocShell.clear(); |
3560 | | |
3561 | 9.91k | return eError == ERRCODE_NONE; |
3562 | 9.91k | } |
3563 | | |
3564 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |