Line data Source code
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 <cstdarg>
21 :
22 : #include <stdio.h>
23 : #include <unotxdoc.hxx>
24 : #include <com/sun/star/text/NotePrintMode.hpp>
25 : #include <sfx2/app.hxx>
26 : #include <com/sun/star/sdb/CommandType.hpp>
27 : #include <com/sun/star/sdb/XDocumentDataSource.hpp>
28 : #include <com/sun/star/frame/XComponentLoader.hpp>
29 : #include <com/sun/star/lang/DisposedException.hpp>
30 : #include <com/sun/star/lang/XEventListener.hpp>
31 : #include <com/sun/star/util/NumberFormatter.hpp>
32 : #include <com/sun/star/sdb/DatabaseContext.hpp>
33 : #include <com/sun/star/sdb/XCompletedConnection.hpp>
34 : #include <com/sun/star/sdb/XCompletedExecution.hpp>
35 : #include <com/sun/star/container/XChild.hpp>
36 : #include <com/sun/star/text/MailMergeEvent.hpp>
37 : #include <com/sun/star/frame/XStorable.hpp>
38 : #include <com/sun/star/task/InteractionHandler.hpp>
39 : #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
40 : #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
41 : #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
42 : #include <com/sun/star/uno/XNamingService.hpp>
43 : #include <com/sun/star/util/XCloseable.hpp>
44 : #include <com/sun/star/beans/XPropertySet.hpp>
45 : #include <sfx2/fcontnr.hxx>
46 : #include <sfx2/filedlghelper.hxx>
47 : #include <sfx2/viewfrm.hxx>
48 : #include <dbconfig.hxx>
49 : #include <swdbtoolsclient.hxx>
50 : #include <pagedesc.hxx>
51 : #include <vcl/lstbox.hxx>
52 : #include <unotools/tempfile.hxx>
53 : #include <unotools/pathoptions.hxx>
54 : #include <svl/urihelper.hxx>
55 : #include <svl/zforlist.hxx>
56 : #include <svl/zformat.hxx>
57 : #include <svl/stritem.hxx>
58 : #include <svl/eitem.hxx>
59 : #include <vcl/oldprintadaptor.hxx>
60 : #include <sfx2/docfile.hxx>
61 : #include <sfx2/progress.hxx>
62 : #include <sfx2/dispatch.hxx>
63 : #include <svl/mailenum.hxx>
64 : #include <cmdid.h>
65 : #include <swmodule.hxx>
66 : #include <view.hxx>
67 : #include <docsh.hxx>
68 : #include <edtwin.hxx>
69 : #include <wrtsh.hxx>
70 : #include <fldbas.hxx>
71 : #include <initui.hxx>
72 : #include <swundo.hxx>
73 : #include <flddat.hxx>
74 : #include <modcfg.hxx>
75 : #include <shellio.hxx>
76 : #include <dbui.hxx>
77 : #include <dbmgr.hxx>
78 : #include <doc.hxx>
79 : #include <swwait.hxx>
80 : #include <swunohelper.hxx>
81 : #include <dbui.hrc>
82 : #include <globals.hrc>
83 : #include <statstr.hrc>
84 : #include <mmconfigitem.hxx>
85 : #include <sfx2/request.hxx>
86 : #include <hintids.hxx>
87 : #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
88 : #include <com/sun/star/sdbc/XRowSet.hpp>
89 : #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
90 : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
91 : #include <com/sun/star/sdb/XQueriesSupplier.hpp>
92 : #include <com/sun/star/sdb/XColumn.hpp>
93 : #include <com/sun/star/sdbc/DataType.hpp>
94 : #include <com/sun/star/sdbc/ResultSetType.hpp>
95 : #include <com/sun/star/mail/MailAttachment.hpp>
96 : #include <comphelper/componentcontext.hxx>
97 : #include <comphelper/processfactory.hxx>
98 : #include <comphelper/property.hxx>
99 : #include <comphelper/string.hxx>
100 : #include <comphelper/types.hxx>
101 : #include <mailmergehelper.hxx>
102 : #include <maildispatcher.hxx>
103 : #include <svtools/htmlcfg.hxx>
104 : #include <i18npool/languagetag.hxx>
105 : #include <com/sun/star/util/XNumberFormatTypes.hpp>
106 : #include <editeng/langitem.hxx>
107 : #include <svl/numuno.hxx>
108 :
109 : #include <unomailmerge.hxx>
110 : #include <sfx2/event.hxx>
111 : #include <vcl/msgbox.hxx>
112 : #include <svx/dataaccessdescriptor.hxx>
113 : #include <osl/mutex.hxx>
114 : #include <rtl/textenc.h>
115 : #include <ndindex.hxx>
116 : #include <pam.hxx>
117 : #include <swcrsr.hxx>
118 : #include <swevent.hxx>
119 : #include <osl/file.hxx>
120 : #include <swabstdlg.hxx>
121 : #include <fmthdft.hxx>
122 : #include <envelp.hrc>
123 : #include <memory>
124 : #include <vector>
125 : #include <unomid.h>
126 : #include <section.hxx>
127 :
128 : using namespace ::osl;
129 : using namespace ::svx;
130 : using namespace ::com::sun::star;
131 : using namespace ::com::sun::star::text;
132 : using namespace ::com::sun::star::uno;
133 : using namespace ::com::sun::star::container;
134 : using namespace ::com::sun::star::frame;
135 : using namespace ::com::sun::star::lang;
136 : using namespace ::com::sun::star::sdb;
137 : using namespace ::com::sun::star::sdbc;
138 : using namespace ::com::sun::star::sdbcx;
139 : using namespace ::com::sun::star::beans;
140 : using namespace ::com::sun::star::util;
141 : using namespace ::com::sun::star::task;
142 : using namespace ::com::sun::star::ui::dialogs;
143 :
144 : #define DB_SEP_SPACE 0
145 : #define DB_SEP_TAB 1
146 : #define DB_SEP_RETURN 2
147 : #define DB_SEP_NEWLINE 3
148 :
149 : const sal_Char cCursor[] = "Cursor";
150 : const sal_Char cCommand[] = "Command";
151 : const sal_Char cCommandType[] = "CommandType";
152 : const sal_Char cDataSourceName[] = "DataSourceName";
153 : const sal_Char cSelection[] = "Selection";
154 : const sal_Char cActiveConnection[] = "ActiveConnection";
155 :
156 : // -----------------------------------------------------------------------------
157 : // Use nameless namespace to avoid to rubbish the global namespace
158 : // -----------------------------------------------------------------------------
159 : namespace
160 : {
161 :
162 0 : bool lcl_getCountFromResultSet( sal_Int32& rCount, const uno::Reference<XResultSet>& xResultSet )
163 : {
164 0 : uno::Reference<XPropertySet> xPrSet(xResultSet, UNO_QUERY);
165 0 : if(xPrSet.is())
166 : {
167 : try
168 : {
169 0 : sal_Bool bFinal = sal_False;
170 0 : Any aFinal = xPrSet->getPropertyValue("IsRowCountFinal");
171 0 : aFinal >>= bFinal;
172 0 : if(!bFinal)
173 : {
174 0 : xResultSet->last();
175 0 : xResultSet->first();
176 : }
177 0 : Any aCount = xPrSet->getPropertyValue("RowCount");
178 0 : if( aCount >>= rCount )
179 0 : return true;
180 : }
181 0 : catch(const Exception&)
182 : {
183 : }
184 : }
185 0 : return false;
186 : }
187 : // copy compatibility options
188 0 : void lcl_CopyCompatibilityOptions( SwWrtShell& rSourceShell, SwWrtShell& rTargetShell)
189 : {
190 0 : IDocumentSettingAccess* pIDsa = rSourceShell.getIDocumentSettingAccess();
191 :
192 0 : rTargetShell.SetParaSpaceMax( pIDsa->get(IDocumentSettingAccess::PARA_SPACE_MAX));
193 0 : rTargetShell.SetParaSpaceMaxAtPages(pIDsa->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES));
194 0 : rTargetShell.SetTabCompat( pIDsa->get(IDocumentSettingAccess::TAB_COMPAT));
195 0 : rTargetShell.SetAddExtLeading( pIDsa->get(IDocumentSettingAccess::ADD_EXT_LEADING));
196 0 : rTargetShell.SetUseVirDev( pIDsa->get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE));
197 0 : rTargetShell.SetAddParaSpacingToTableCells( pIDsa->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS));
198 0 : rTargetShell.SetUseFormerLineSpacing( pIDsa->get(IDocumentSettingAccess::OLD_LINE_SPACING));
199 0 : rTargetShell.SetUseFormerObjectPositioning( pIDsa->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS));
200 0 : rTargetShell.SetConsiderWrapOnObjPos( pIDsa->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION));
201 0 : rTargetShell.SetUseFormerTextWrapping( pIDsa->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING));
202 0 : }
203 : }
204 :
205 : class SwConnectionDisposedListener_Impl : public cppu::WeakImplHelper1
206 : < lang::XEventListener >
207 : {
208 : SwNewDBMgr& rDBMgr;
209 :
210 : virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException);
211 : public:
212 : SwConnectionDisposedListener_Impl(SwNewDBMgr& rMgr);
213 : ~SwConnectionDisposedListener_Impl();
214 :
215 : };
216 :
217 102 : struct SwNewDBMgr_Impl
218 : {
219 : SwDSParam* pMergeData;
220 : AbstractMailMergeDlg* pMergeDialog;
221 : uno::Reference<lang::XEventListener> xDisposeListener;
222 :
223 276 : SwNewDBMgr_Impl(SwNewDBMgr& rDBMgr)
224 : :pMergeData(0)
225 : ,pMergeDialog(0)
226 276 : ,xDisposeListener(new SwConnectionDisposedListener_Impl(rDBMgr))
227 276 : {}
228 : };
229 :
230 0 : static void lcl_InitNumberFormatter(SwDSParam& rParam, uno::Reference<XDataSource> xSource)
231 : {
232 0 : uno::Reference<XComponentContext> xContext = ::comphelper::getProcessComponentContext();
233 0 : rParam.xFormatter = uno::Reference<util::XNumberFormatter>(util::NumberFormatter::create(xContext), UNO_QUERY);
234 0 : if(!xSource.is())
235 0 : xSource = SwNewDBMgr::getDataSourceAsParent(rParam.xConnection, rParam.sDataSource);
236 :
237 0 : uno::Reference<XPropertySet> xSourceProps(xSource, UNO_QUERY);
238 0 : if(xSourceProps.is())
239 : {
240 0 : Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier");
241 0 : if(aFormats.hasValue())
242 : {
243 0 : uno::Reference<XNumberFormatsSupplier> xSuppl;
244 0 : aFormats >>= xSuppl;
245 0 : if(xSuppl.is())
246 : {
247 0 : uno::Reference< XPropertySet > xSettings = xSuppl->getNumberFormatSettings();
248 0 : Any aNull = xSettings->getPropertyValue("NullDate");
249 0 : aNull >>= rParam.aNullDate;
250 0 : if(rParam.xFormatter.is())
251 0 : rParam.xFormatter->attachNumberFormatsSupplier(xSuppl);
252 0 : }
253 0 : }
254 0 : }
255 0 : }
256 :
257 0 : static sal_Bool lcl_MoveAbsolute(SwDSParam* pParam, long nAbsPos)
258 : {
259 0 : sal_Bool bRet = sal_False;
260 : try
261 : {
262 0 : if(pParam->bScrollable)
263 : {
264 0 : bRet = pParam->xResultSet->absolute( nAbsPos );
265 : }
266 : else
267 : {
268 : OSL_FAIL("no absolute positioning available");
269 : }
270 : }
271 0 : catch(const Exception&)
272 : {
273 : }
274 0 : return bRet;
275 : }
276 :
277 0 : static sal_Bool lcl_GetColumnCnt(SwDSParam* pParam,
278 : const String& rColumnName, long nLanguage, rtl::OUString& rResult, double* pNumber)
279 : {
280 0 : uno::Reference< XColumnsSupplier > xColsSupp( pParam->xResultSet, UNO_QUERY );
281 0 : uno::Reference<XNameAccess> xCols;
282 : try
283 : {
284 0 : xCols = xColsSupp->getColumns();
285 : }
286 0 : catch(const lang::DisposedException&)
287 : {
288 : }
289 0 : if(!xCols.is() || !xCols->hasByName(rColumnName))
290 0 : return sal_False;
291 0 : Any aCol = xCols->getByName(rColumnName);
292 0 : uno::Reference< XPropertySet > xColumnProps;
293 0 : aCol >>= xColumnProps;
294 :
295 0 : SwDBFormatData aFormatData;
296 0 : if(!pParam->xFormatter.is())
297 : {
298 : uno::Reference<XDataSource> xSource = SwNewDBMgr::getDataSourceAsParent(
299 0 : pParam->xConnection,pParam->sDataSource);
300 0 : lcl_InitNumberFormatter(*pParam, xSource );
301 : }
302 0 : aFormatData.aNullDate = pParam->aNullDate;
303 0 : aFormatData.xFormatter = pParam->xFormatter;
304 :
305 0 : aFormatData.aLocale = LanguageTag( (LanguageType)nLanguage ).getLocale();
306 :
307 0 : rResult = SwNewDBMgr::GetDBField( xColumnProps, aFormatData, pNumber);
308 0 : return sal_True;
309 : };
310 :
311 : /*--------------------------------------------------------------------
312 : Description: import data
313 : --------------------------------------------------------------------*/
314 0 : sal_Bool SwNewDBMgr::MergeNew(const SwMergeDescriptor& rMergeDesc )
315 : {
316 0 : SetMergeType( rMergeDesc.nMergeType );
317 :
318 : OSL_ENSURE(!bInMerge && !pImpl->pMergeData, "merge already activated!");
319 :
320 0 : SwDBData aData;
321 0 : aData.nCommandType = CommandType::TABLE;
322 0 : uno::Reference<XResultSet> xResSet;
323 0 : Sequence<Any> aSelection;
324 0 : uno::Reference< XConnection> xConnection;
325 :
326 0 : aData.sDataSource = rMergeDesc.rDescriptor.getDataSource();
327 0 : rMergeDesc.rDescriptor[daCommand] >>= aData.sCommand;
328 0 : rMergeDesc.rDescriptor[daCommandType] >>= aData.nCommandType;
329 :
330 0 : if ( rMergeDesc.rDescriptor.has(daCursor) )
331 0 : rMergeDesc.rDescriptor[daCursor] >>= xResSet;
332 0 : if ( rMergeDesc.rDescriptor.has(daSelection) )
333 0 : rMergeDesc.rDescriptor[daSelection] >>= aSelection;
334 0 : if ( rMergeDesc.rDescriptor.has(daConnection) )
335 0 : rMergeDesc.rDescriptor[daConnection] >>= xConnection;
336 :
337 0 : if(aData.sDataSource.isEmpty() || aData.sCommand.isEmpty() || !xResSet.is())
338 : {
339 0 : return sal_False;
340 : }
341 :
342 0 : pImpl->pMergeData = new SwDSParam(aData, xResSet, aSelection);
343 0 : SwDSParam* pTemp = FindDSData(aData, sal_False);
344 0 : if(pTemp)
345 0 : *pTemp = *pImpl->pMergeData;
346 : else
347 : {
348 : // calls from the calculator may have added a connection with an invalid commandtype
349 : //"real" data base connections added here have to re-use the already available
350 : //DSData and set the correct CommandType
351 0 : SwDBData aTempData(aData);
352 0 : aData.nCommandType = -1;
353 0 : pTemp = FindDSData(aData, sal_False);
354 0 : if(pTemp)
355 0 : *pTemp = *pImpl->pMergeData;
356 : else
357 : {
358 0 : SwDSParam* pInsert = new SwDSParam(*pImpl->pMergeData);
359 0 : aDataSourceParams.push_back(pInsert);
360 : try
361 : {
362 0 : uno::Reference<XComponent> xComponent(pInsert->xConnection, UNO_QUERY);
363 0 : if(xComponent.is())
364 0 : xComponent->addEventListener(pImpl->xDisposeListener);
365 : }
366 0 : catch(const Exception&)
367 : {
368 : }
369 0 : }
370 : }
371 0 : if(!pImpl->pMergeData->xConnection.is())
372 0 : pImpl->pMergeData->xConnection = xConnection;
373 : // add an XEventListener
374 :
375 : try{
376 : //set to start position
377 0 : if(pImpl->pMergeData->aSelection.getLength())
378 : {
379 0 : sal_Int32 nPos = 0;
380 0 : pImpl->pMergeData->aSelection.getConstArray()[ pImpl->pMergeData->nSelectionIndex++ ] >>= nPos;
381 0 : pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->absolute( nPos );
382 0 : pImpl->pMergeData->CheckEndOfDB();
383 0 : if(pImpl->pMergeData->nSelectionIndex >= pImpl->pMergeData->aSelection.getLength())
384 0 : pImpl->pMergeData->bEndOfDB = sal_True;
385 : }
386 : else
387 : {
388 0 : pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->first();
389 0 : pImpl->pMergeData->CheckEndOfDB();
390 : }
391 : }
392 0 : catch(const Exception&)
393 : {
394 0 : pImpl->pMergeData->bEndOfDB = sal_True;
395 0 : pImpl->pMergeData->CheckEndOfDB();
396 : OSL_FAIL("exception in MergeNew()");
397 : }
398 :
399 0 : uno::Reference<XDataSource> xSource = SwNewDBMgr::getDataSourceAsParent(xConnection,aData.sDataSource);
400 :
401 0 : lcl_InitNumberFormatter(*pImpl->pMergeData, xSource);
402 :
403 0 : rMergeDesc.rSh.ChgDBData(aData);
404 0 : bInMerge = sal_True;
405 :
406 0 : if (IsInitDBFields())
407 : {
408 : // with database fields without DB-Name, use DB-Name from Doc
409 0 : std::vector<String> aDBNames;
410 0 : aDBNames.push_back(String());
411 0 : SwDBData aInsertData = rMergeDesc.rSh.GetDBData();
412 0 : String sDBName = aInsertData.sDataSource;
413 0 : sDBName += DB_DELIM;
414 0 : sDBName += (String)aInsertData.sCommand;
415 0 : sDBName += DB_DELIM;
416 0 : sDBName += String::CreateFromInt32(aInsertData.nCommandType);
417 0 : rMergeDesc.rSh.ChangeDBFields( aDBNames, sDBName);
418 0 : SetInitDBFields(sal_False);
419 : }
420 :
421 0 : sal_Bool bRet = sal_True;
422 0 : switch(rMergeDesc.nMergeType)
423 : {
424 : case DBMGR_MERGE:
425 0 : bRet = Merge(&rMergeDesc.rSh);
426 0 : break;
427 :
428 : case DBMGR_MERGE_MAILMERGE: // printing merge from 'old' merge dialog or from UNO-component
429 : case DBMGR_MERGE_MAILING:
430 : case DBMGR_MERGE_MAILFILES:
431 : case DBMGR_MERGE_SINGLE_FILE:
432 : // save files and send them as e-Mail if required
433 : bRet = MergeMailFiles(&rMergeDesc.rSh,
434 0 : rMergeDesc);
435 0 : break;
436 :
437 : default:
438 : // insert selected entries
439 : // (was: InsertRecord)
440 0 : ImportFromConnection(&rMergeDesc.rSh);
441 0 : break;
442 : }
443 :
444 0 : EndMerge();
445 0 : return bRet;
446 : }
447 :
448 : /*--------------------------------------------------------------------
449 : Description: import data
450 : --------------------------------------------------------------------*/
451 0 : sal_Bool SwNewDBMgr::Merge(SwWrtShell* pSh)
452 : {
453 0 : pSh->StartAllAction();
454 :
455 0 : pSh->ViewShell::UpdateFlds(sal_True);
456 0 : pSh->SetModified();
457 :
458 0 : pSh->EndAllAction();
459 :
460 0 : return sal_True;
461 : }
462 :
463 0 : void SwNewDBMgr::ImportFromConnection( SwWrtShell* pSh )
464 : {
465 0 : if(pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB)
466 : {
467 : {
468 0 : pSh->StartAllAction();
469 0 : pSh->StartUndo(UNDO_EMPTY);
470 0 : sal_Bool bGroupUndo(pSh->DoesGroupUndo());
471 0 : pSh->DoGroupUndo(sal_False);
472 :
473 0 : if( pSh->HasSelection() )
474 0 : pSh->DelRight();
475 :
476 0 : SwWait *pWait = 0;
477 :
478 : {
479 0 : sal_uLong i = 0;
480 0 : do {
481 :
482 0 : ImportDBEntry(pSh);
483 0 : if( 10 == ++i )
484 0 : pWait = new SwWait( *pSh->GetView().GetDocShell(), sal_True);
485 :
486 0 : } while(ToNextMergeRecord());
487 : }
488 :
489 0 : pSh->DoGroupUndo(bGroupUndo);
490 0 : pSh->EndUndo(UNDO_EMPTY);
491 0 : pSh->EndAllAction();
492 0 : delete pWait;
493 : }
494 : }
495 0 : }
496 :
497 0 : static String lcl_FindColumn(const String& sFormatStr,sal_uInt16 &nUsedPos, sal_uInt8 &nSeparator)
498 : {
499 0 : String sReturn;
500 0 : sal_uInt16 nLen = sFormatStr.Len();
501 0 : nSeparator = 0xff;
502 0 : while(nUsedPos < nLen && nSeparator == 0xff)
503 : {
504 0 : sal_Unicode cAkt = sFormatStr.GetChar(nUsedPos);
505 0 : switch(cAkt)
506 : {
507 : case ',':
508 0 : nSeparator = DB_SEP_SPACE;
509 0 : break;
510 : case ';':
511 0 : nSeparator = DB_SEP_RETURN;
512 0 : break;
513 : case ':':
514 0 : nSeparator = DB_SEP_TAB;
515 0 : break;
516 : case '#':
517 0 : nSeparator = DB_SEP_NEWLINE;
518 0 : break;
519 : default:
520 0 : sReturn += cAkt;
521 : }
522 0 : nUsedPos++;
523 :
524 : }
525 0 : return sReturn;
526 : }
527 :
528 0 : void SwNewDBMgr::ImportDBEntry(SwWrtShell* pSh)
529 : {
530 0 : if(pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB)
531 : {
532 0 : uno::Reference< XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, UNO_QUERY );
533 0 : uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
534 0 : String sFormatStr;
535 0 : sal_uInt16 nFmtLen = sFormatStr.Len();
536 0 : if( nFmtLen )
537 : {
538 0 : const char cSpace = ' ';
539 0 : const char cTab = '\t';
540 0 : sal_uInt16 nUsedPos = 0;
541 : sal_uInt8 nSeparator;
542 0 : String sColumn = lcl_FindColumn(sFormatStr, nUsedPos, nSeparator);
543 0 : while( sColumn.Len() )
544 : {
545 0 : if(!xCols->hasByName(sColumn))
546 0 : return;
547 0 : Any aCol = xCols->getByName(sColumn);
548 0 : uno::Reference< XPropertySet > xColumnProp;
549 0 : aCol >>= xColumnProp;
550 0 : if(xColumnProp.is())
551 : {
552 0 : SwDBFormatData aDBFormat;
553 0 : String sInsert = GetDBField( xColumnProp, aDBFormat);
554 0 : if( DB_SEP_SPACE == nSeparator )
555 0 : sInsert += cSpace;
556 0 : else if( DB_SEP_TAB == nSeparator)
557 0 : sInsert += cTab;
558 0 : pSh->Insert(sInsert);
559 0 : if( DB_SEP_RETURN == nSeparator)
560 0 : pSh->SplitNode();
561 0 : else if(DB_SEP_NEWLINE == nSeparator)
562 0 : pSh->InsertLineBreak();
563 : }
564 : else
565 : {
566 : // column not found -> show error
567 0 : rtl::OUStringBuffer sInsert;
568 0 : sInsert.append('?').append(sColumn).append('?');
569 0 : pSh->Insert(sInsert.makeStringAndClear());
570 : }
571 0 : sColumn = lcl_FindColumn(sFormatStr, nUsedPos, nSeparator);
572 0 : }
573 0 : pSh->SplitNode();
574 : }
575 : else
576 : {
577 0 : String sStr;
578 0 : Sequence<rtl::OUString> aColNames = xCols->getElementNames();
579 0 : const rtl::OUString* pColNames = aColNames.getConstArray();
580 0 : long nLength = aColNames.getLength();
581 0 : for(long i = 0; i < nLength; i++)
582 : {
583 0 : Any aCol = xCols->getByName(pColNames[i]);
584 0 : uno::Reference< XPropertySet > xColumnProp;
585 0 : aCol >>= xColumnProp;
586 0 : SwDBFormatData aDBFormat;
587 0 : sStr += GetDBField( xColumnProp, aDBFormat);
588 0 : if (i < nLength - 1)
589 0 : sStr += '\t';
590 0 : }
591 0 : pSh->SwEditShell::Insert2(sStr);
592 0 : pSh->SwFEShell::SplitNode(); // line feed
593 0 : }
594 : }
595 : }
596 :
597 : /*--------------------------------------------------------------------
598 : Description: fill Listbox with tablelist
599 : --------------------------------------------------------------------*/
600 0 : sal_Bool SwNewDBMgr::GetTableNames(ListBox* pListBox, const String& rDBName)
601 : {
602 0 : sal_Bool bRet = sal_False;
603 0 : String sOldTableName(pListBox->GetSelectEntry());
604 0 : pListBox->Clear();
605 0 : SwDSParam* pParam = FindDSConnection(rDBName, sal_False);
606 0 : uno::Reference< XConnection> xConnection;
607 0 : if(pParam && pParam->xConnection.is())
608 0 : xConnection = pParam->xConnection;
609 : else
610 : {
611 0 : rtl::OUString sDBName(rDBName);
612 0 : if ( !sDBName.isEmpty() )
613 0 : xConnection = RegisterConnection( sDBName );
614 : }
615 0 : if(xConnection.is())
616 : {
617 0 : uno::Reference<XTablesSupplier> xTSupplier = uno::Reference<XTablesSupplier>(xConnection, UNO_QUERY);
618 0 : if(xTSupplier.is())
619 : {
620 0 : uno::Reference<XNameAccess> xTbls = xTSupplier->getTables();
621 0 : Sequence<rtl::OUString> aTbls = xTbls->getElementNames();
622 0 : const rtl::OUString* pTbls = aTbls.getConstArray();
623 0 : for(long i = 0; i < aTbls.getLength(); i++)
624 : {
625 0 : sal_uInt16 nEntry = pListBox->InsertEntry(pTbls[i]);
626 0 : pListBox->SetEntryData(nEntry, (void*)0);
627 0 : }
628 : }
629 0 : uno::Reference<XQueriesSupplier> xQSupplier = uno::Reference<XQueriesSupplier>(xConnection, UNO_QUERY);
630 0 : if(xQSupplier.is())
631 : {
632 0 : uno::Reference<XNameAccess> xQueries = xQSupplier->getQueries();
633 0 : Sequence<rtl::OUString> aQueries = xQueries->getElementNames();
634 0 : const rtl::OUString* pQueries = aQueries.getConstArray();
635 0 : for(long i = 0; i < aQueries.getLength(); i++)
636 : {
637 0 : sal_uInt16 nEntry = pListBox->InsertEntry(pQueries[i]);
638 0 : pListBox->SetEntryData(nEntry, (void*)1);
639 0 : }
640 : }
641 0 : if (sOldTableName.Len())
642 0 : pListBox->SelectEntry(sOldTableName);
643 0 : bRet = sal_True;
644 : }
645 0 : return bRet;
646 : }
647 :
648 : /*--------------------------------------------------------------------
649 : Description: fill Listbox with column names of a database
650 : --------------------------------------------------------------------*/
651 0 : sal_Bool SwNewDBMgr::GetColumnNames(ListBox* pListBox,
652 : const String& rDBName, const String& rTableName, sal_Bool bAppend)
653 : {
654 0 : if (!bAppend)
655 0 : pListBox->Clear();
656 0 : SwDBData aData;
657 0 : aData.sDataSource = rDBName;
658 0 : aData.sCommand = rTableName;
659 0 : aData.nCommandType = -1;
660 0 : SwDSParam* pParam = FindDSData(aData, sal_False);
661 0 : uno::Reference< XConnection> xConnection;
662 0 : if(pParam && pParam->xConnection.is())
663 0 : xConnection = pParam->xConnection;
664 : else
665 : {
666 0 : rtl::OUString sDBName(rDBName);
667 0 : xConnection = RegisterConnection( sDBName );
668 : }
669 0 : uno::Reference< XColumnsSupplier> xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName);
670 0 : if(xColsSupp.is())
671 : {
672 0 : uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
673 0 : const Sequence<rtl::OUString> aColNames = xCols->getElementNames();
674 0 : const rtl::OUString* pColNames = aColNames.getConstArray();
675 0 : for(int nCol = 0; nCol < aColNames.getLength(); nCol++)
676 : {
677 0 : pListBox->InsertEntry(pColNames[nCol]);
678 : }
679 0 : ::comphelper::disposeComponent( xColsSupp );
680 : }
681 0 : return(sal_True);
682 : }
683 :
684 0 : sal_Bool SwNewDBMgr::GetColumnNames(ListBox* pListBox,
685 : uno::Reference< XConnection> xConnection,
686 : const String& rTableName, sal_Bool bAppend)
687 : {
688 0 : if (!bAppend)
689 0 : pListBox->Clear();
690 0 : uno::Reference< XColumnsSupplier> xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName);
691 0 : if(xColsSupp.is())
692 : {
693 0 : uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
694 0 : const Sequence<rtl::OUString> aColNames = xCols->getElementNames();
695 0 : const rtl::OUString* pColNames = aColNames.getConstArray();
696 0 : for(int nCol = 0; nCol < aColNames.getLength(); nCol++)
697 : {
698 0 : pListBox->InsertEntry(pColNames[nCol]);
699 : }
700 0 : ::comphelper::disposeComponent( xColsSupp );
701 : }
702 0 : return(sal_True);
703 : }
704 :
705 : /*--------------------------------------------------------------------
706 : Description: CTOR
707 : --------------------------------------------------------------------*/
708 276 : SwNewDBMgr::SwNewDBMgr() :
709 : nMergeType(DBMGR_INSERT),
710 : bInitDBFields(sal_False),
711 : bInMerge(sal_False),
712 : bMergeSilent(sal_False),
713 : bMergeLock(sal_False),
714 276 : pImpl(new SwNewDBMgr_Impl(*this)),
715 552 : pMergeEvtSrc(NULL)
716 : {
717 276 : }
718 :
719 204 : SwNewDBMgr::~SwNewDBMgr()
720 : {
721 102 : for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.size(); nPos++)
722 : {
723 0 : SwDSParam* pParam = &aDataSourceParams[nPos];
724 0 : if(pParam->xConnection.is())
725 : {
726 : try
727 : {
728 0 : uno::Reference<XComponent> xComp(pParam->xConnection, UNO_QUERY);
729 0 : if(xComp.is())
730 0 : xComp->dispose();
731 : }
732 0 : catch(const RuntimeException&)
733 : {
734 : //may be disposed already since multiple entries may have used the same connection
735 : }
736 : }
737 : }
738 102 : delete pImpl;
739 102 : }
740 :
741 : /*--------------------------------------------------------------------
742 : Description: save bulk letters as single documents
743 : --------------------------------------------------------------------*/
744 0 : static String lcl_FindUniqueName(SwWrtShell* pTargetShell, const String& rStartingPageDesc, sal_uLong nDocNo )
745 : {
746 0 : do
747 : {
748 0 : String sTest = rStartingPageDesc;
749 0 : sTest += String::CreateFromInt32( nDocNo );
750 0 : if( !pTargetShell->FindPageDescByName( sTest ) )
751 0 : return sTest;
752 0 : ++nDocNo;
753 : }while(true);
754 : }
755 :
756 0 : static void lcl_CopyDynamicDefaults( const SwDoc& rSource, SwDoc& rTarget )
757 : {
758 : sal_uInt16 aRangeOfDefaults[] = {
759 : RES_FRMATR_BEGIN, RES_FRMATR_END-1,
760 : RES_CHRATR_BEGIN, RES_CHRATR_END-1,
761 : RES_PARATR_BEGIN, RES_PARATR_END-1,
762 : RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
763 : RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
764 : 0
765 0 : };
766 :
767 0 : SfxItemSet aNewDefaults( rTarget.GetAttrPool(), aRangeOfDefaults );
768 :
769 : sal_uInt16 nWhich;
770 0 : sal_uInt16 nRange = 0;
771 0 : while( aRangeOfDefaults[nRange] != 0)
772 : {
773 0 : for( nWhich = aRangeOfDefaults[nRange]; nWhich < aRangeOfDefaults[nRange + 1]; ++nWhich )
774 : {
775 0 : const SfxPoolItem& rSourceAttr = rSource.GetDefault( nWhich );
776 0 : if( rSourceAttr != rTarget.GetDefault( nWhich ) )
777 0 : aNewDefaults.Put( rSourceAttr );
778 : }
779 0 : nRange += 2;
780 : }
781 0 : if( aNewDefaults.Count() )
782 0 : rTarget.SetDefault( aNewDefaults );
783 0 : }
784 :
785 0 : static void lcl_CopyFollowPageDesc(
786 : SwWrtShell& rTargetShell,
787 : const SwPageDesc& rSourcePageDesc,
788 : const SwPageDesc& rTargetPageDesc,
789 : const sal_uLong nDocNo )
790 : {
791 : //now copy the follow page desc, too
792 0 : const SwPageDesc* pFollowPageDesc = rSourcePageDesc.GetFollow();
793 0 : String sFollowPageDesc = pFollowPageDesc->GetName();
794 0 : if( sFollowPageDesc != rSourcePageDesc.GetName() )
795 : {
796 0 : SwDoc* pTargetDoc = rTargetShell.GetDoc();
797 0 : String sNewFollowPageDesc = lcl_FindUniqueName(&rTargetShell, sFollowPageDesc, nDocNo );
798 0 : sal_uInt16 nNewDesc = pTargetDoc->MakePageDesc( sNewFollowPageDesc );
799 0 : SwPageDesc& rTargetFollowPageDesc = pTargetDoc->GetPageDesc( nNewDesc );
800 :
801 0 : pTargetDoc->CopyPageDesc( *pFollowPageDesc, rTargetFollowPageDesc, false );
802 0 : SwPageDesc aDesc( rTargetPageDesc );
803 0 : aDesc.SetFollow( &rTargetFollowPageDesc );
804 0 : pTargetDoc->ChgPageDesc( rTargetPageDesc.GetName(), aDesc );
805 0 : }
806 0 : }
807 :
808 0 : static void lcl_RemoveSectionLinks( SwWrtShell& rWorkShell )
809 : {
810 : //reset all links of the sections of synchronized labels
811 0 : sal_uInt16 nSections = rWorkShell.GetSectionFmtCount();
812 0 : for( sal_uInt16 nSection = 0; nSection < nSections; ++nSection )
813 : {
814 0 : SwSectionData aSectionData( *rWorkShell.GetSectionFmt( nSection ).GetSection() );
815 0 : if( aSectionData.GetType() == FILE_LINK_SECTION )
816 : {
817 0 : aSectionData.SetType( CONTENT_SECTION );
818 0 : aSectionData.SetLinkFileName( String() );
819 0 : rWorkShell.UpdateSection( nSection, aSectionData );
820 : }
821 0 : }
822 0 : rWorkShell.SetLabelDoc( sal_False );
823 0 : }
824 :
825 0 : sal_Bool SwNewDBMgr::MergeMailFiles(SwWrtShell* pSourceShell,
826 : const SwMergeDescriptor& rMergeDescriptor)
827 : {
828 : //check if the doc is synchronized and contains at least one linked section
829 0 : sal_Bool bSynchronizedDoc = pSourceShell->IsLabelDoc() && pSourceShell->GetSectionFmtCount() > 1;
830 0 : sal_Bool bLoop = sal_True;
831 0 : sal_Bool bEMail = rMergeDescriptor.nMergeType == DBMGR_MERGE_MAILING;
832 0 : const bool bAsSingleFile = rMergeDescriptor.nMergeType == DBMGR_MERGE_SINGLE_FILE;
833 :
834 0 : ::rtl::Reference< MailDispatcher > xMailDispatcher;
835 0 : ::rtl::OUString sBodyMimeType;
836 0 : rtl_TextEncoding eEncoding = ::osl_getThreadTextEncoding();
837 :
838 0 : if(bEMail)
839 : {
840 0 : xMailDispatcher.set( new MailDispatcher(rMergeDescriptor.xSmtpServer));
841 0 : if(!rMergeDescriptor.bSendAsAttachment && rMergeDescriptor.bSendAsHTML)
842 : {
843 0 : sBodyMimeType = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("text/html; charset="));
844 : sBodyMimeType += ::rtl::OUString::createFromAscii(
845 0 : rtl_getBestMimeCharsetFromTextEncoding( eEncoding ));
846 0 : SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
847 0 : eEncoding = rHtmlOptions.GetTextEncoding();
848 : }
849 : else
850 : sBodyMimeType =
851 0 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("text/plain; charset=UTF-8; format=flowed"));
852 : }
853 :
854 0 : uno::Reference< XPropertySet > xColumnProp;
855 : {
856 0 : sal_Bool bColumnName = sEMailAddrFld.Len() > 0;
857 :
858 0 : if (bColumnName)
859 : {
860 0 : uno::Reference< XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, UNO_QUERY );
861 0 : uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
862 0 : if(!xCols->hasByName(sEMailAddrFld))
863 0 : return sal_False;
864 0 : Any aCol = xCols->getByName(sEMailAddrFld);
865 0 : aCol >>= xColumnProp;
866 : }
867 :
868 0 : SfxDispatcher* pSfxDispatcher = pSourceShell->GetView().GetViewFrame()->GetDispatcher();
869 0 : SwDocShell* pSourrceDocSh = pSourceShell->GetView().GetDocShell();
870 0 : pSfxDispatcher->Execute( pSourrceDocSh->HasName() ? SID_SAVEDOC : SID_SAVEASDOC, SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD);
871 : // has document been saved successfully?
872 0 : if( !pSourrceDocSh->IsModified() )
873 : {
874 0 : SfxMedium* pOrig = pSourceShell->GetView().GetDocShell()->GetMedium();
875 0 : String sSourceDocumentURL(pOrig->GetURLObject().GetMainURL( INetURLObject::NO_DECODE ));
876 : const SfxFilter* pSfxFlt = SwIoSystem::GetFileFilter(
877 0 : sSourceDocumentURL, ::aEmptyStr );
878 0 : const SfxFilter* pStoreToFilter = pSfxFlt;
879 0 : SfxFilterContainer* pFilterContainer = SwDocShell::Factory().GetFilterContainer();
880 0 : const String* pStoreToFilterOptions = 0;
881 : // if a save_to filter is set then use it - otherwise use the default
882 0 : if( bEMail && !rMergeDescriptor.bSendAsAttachment )
883 : {
884 0 : rtl::OUString sExtension = rMergeDescriptor.bSendAsHTML ? rtl::OUString("html") : rtl::OUString("txt");
885 0 : pStoreToFilter = pFilterContainer->GetFilter4Extension(sExtension, SFX_FILTER_EXPORT);
886 : }
887 0 : else if( rMergeDescriptor.sSaveToFilter.Len())
888 : {
889 : const SfxFilter* pFilter =
890 0 : pFilterContainer->GetFilter4FilterName( rMergeDescriptor.sSaveToFilter );
891 0 : if(pFilter)
892 : {
893 0 : pStoreToFilter = pFilter;
894 0 : if(rMergeDescriptor.sSaveToFilterOptions.Len())
895 0 : pStoreToFilterOptions = &rMergeDescriptor.sSaveToFilterOptions;
896 : }
897 : }
898 0 : bCancel = sal_False;
899 :
900 : // in case of creating a single resulting file this has to be created here
901 0 : SwWrtShell* pTargetShell = 0;
902 :
903 : // the shell will be explicitly closed at the end of the method, but it is
904 : // still more safe to use SfxObjectShellLock here
905 0 : SfxObjectShellLock xTargetDocShell;
906 :
907 0 : SwView* pTargetView = 0;
908 0 : std::auto_ptr< utl::TempFile > aTempFile;
909 0 : String sModifiedStartingPageDesc;
910 0 : String sStartingPageDesc;
911 0 : sal_uInt16 nStartingPageNo = 0;
912 0 : bool bPageStylesWithHeaderFooter = false;
913 0 : if(bAsSingleFile || rMergeDescriptor.bCreateSingleFile)
914 : {
915 : // create a target docshell to put the merged document into
916 0 : xTargetDocShell = new SwDocShell( SFX_CREATE_MODE_STANDARD );
917 0 : xTargetDocShell->DoInitNew( 0 );
918 0 : SfxViewFrame* pTargetFrame = SfxViewFrame::LoadHiddenDocument( *xTargetDocShell, 0 );
919 :
920 0 : pTargetView = static_cast<SwView*>( pTargetFrame->GetViewShell() );
921 :
922 : //initiate SelectShell() to create sub shells
923 0 : pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() );
924 0 : pTargetShell = pTargetView->GetWrtShellPtr();
925 : //copy the styles from the source to the target document
926 0 : SwgReaderOption aOpt;
927 0 : aOpt.SetTxtFmts( sal_True );
928 0 : aOpt.SetFrmFmts( sal_True );
929 0 : aOpt.SetPageDescs( sal_True );
930 0 : aOpt.SetNumRules( sal_True );
931 0 : aOpt.SetMerge( sal_False );
932 : pTargetView->GetDocShell()->LoadStylesFromFile(
933 0 : sSourceDocumentURL, aOpt, sal_True );
934 : //determine the page style and number used at the start of the source document
935 0 : pSourceShell->SttEndDoc(sal_True);
936 0 : nStartingPageNo = pSourceShell->GetVirtPageNum();
937 : sStartingPageDesc = sModifiedStartingPageDesc = pSourceShell->GetPageDesc(
938 0 : pSourceShell->GetCurPageDesc()).GetName();
939 : // copy compatibility options
940 0 : lcl_CopyCompatibilityOptions( *pSourceShell, *pTargetShell);
941 : // #72821# copy dynamic defaults
942 0 : lcl_CopyDynamicDefaults( *pSourceShell->GetDoc(), *pTargetShell->GetDoc() );
943 : // #i72517#
944 0 : const SwPageDesc* pSourcePageDesc = pSourceShell->FindPageDescByName( sStartingPageDesc );
945 0 : const SwFrmFmt& rMaster = pSourcePageDesc->GetMaster();
946 0 : bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive() ||
947 0 : rMaster.GetFooter().IsActive();
948 :
949 : }
950 :
951 0 : PrintMonitor aPrtMonDlg(&pSourceShell->GetView().GetEditWin(), PrintMonitor::MONITOR_TYPE_PRINT);
952 0 : aPrtMonDlg.aDocName.SetText(pSourceShell->GetView().GetDocShell()->GetTitle(22));
953 :
954 0 : aPrtMonDlg.aCancel.SetClickHdl(LINK(this, SwNewDBMgr, PrtCancelHdl));
955 0 : if (!IsMergeSilent())
956 0 : aPrtMonDlg.Show();
957 :
958 : // Progress, to prohibit KeyInputs
959 0 : SfxProgress aProgress(pSourrceDocSh, ::aEmptyStr, 1);
960 :
961 : // lock all dispatchers
962 0 : SfxViewFrame* pViewFrm = SfxViewFrame::GetFirst(pSourrceDocSh);
963 0 : while (pViewFrm)
964 : {
965 0 : pViewFrm->GetDispatcher()->Lock(sal_True);
966 0 : pViewFrm = SfxViewFrame::GetNext(*pViewFrm, pSourrceDocSh);
967 : }
968 0 : sal_uLong nDocNo = 1;
969 :
970 : long nStartRow, nEndRow;
971 : // collect temporary files
972 0 : ::std::vector< String> aFilesToRemove;
973 0 : do
974 : {
975 0 : nStartRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
976 : {
977 0 : String sPath(sSubject);
978 :
979 0 : String sAddress;
980 0 : if( !bEMail && bColumnName )
981 : {
982 0 : SwDBFormatData aDBFormat;
983 0 : aDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
984 0 : aDBFormat.aNullDate = pImpl->pMergeData->aNullDate;
985 0 : sAddress = GetDBField( xColumnProp, aDBFormat);
986 0 : if (!sAddress.Len())
987 0 : sAddress = '_';
988 0 : sPath += sAddress;
989 : }
990 :
991 : // create a new temporary file name - only done once in case of bCreateSingleFile
992 0 : if( 1 == nDocNo || (!rMergeDescriptor.bCreateSingleFile && !bAsSingleFile) )
993 : {
994 0 : INetURLObject aEntry(sPath);
995 0 : String sLeading;
996 : //#i97667# if the name is from a database field then it will be used _as is_
997 0 : if( sAddress.Len() )
998 0 : sLeading = sAddress;
999 : else
1000 0 : sLeading = aEntry.GetBase();
1001 0 : aEntry.removeSegment();
1002 0 : sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE );
1003 0 : String sExt(comphelper::string::stripStart(pStoreToFilter->GetDefaultExtension(), '*'));
1004 : aTempFile = std::auto_ptr< utl::TempFile >(
1005 0 : new utl::TempFile(sLeading,&sExt,&sPath ));
1006 0 : if( bAsSingleFile )
1007 0 : aTempFile->EnableKillingFile();
1008 : }
1009 :
1010 0 : if( !aTempFile->IsValid() )
1011 : {
1012 0 : ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED );
1013 0 : bLoop = sal_False;
1014 0 : bCancel = sal_True;
1015 : }
1016 : else
1017 : {
1018 0 : INetURLObject aTempFileURL(aTempFile->GetURL());
1019 0 : aPrtMonDlg.aPrinter.SetText( aTempFileURL.GetBase() );
1020 0 : String sStat(SW_RES(STR_STATSTR_LETTER)); // Brief
1021 0 : sStat += ' ';
1022 0 : sStat += String::CreateFromInt32( nDocNo );
1023 0 : aPrtMonDlg.aPrintInfo.SetText(sStat);
1024 :
1025 : // computation time for Save-Monitor:
1026 0 : for (sal_uInt16 i = 0; i < 10; i++)
1027 0 : Application::Reschedule();
1028 :
1029 : // Create and save new document
1030 : // The SfxObjectShell will be closed explicitly later but it is more safe to use SfxObjectShellLock here
1031 0 : SfxObjectShellLock xWorkDocSh( new SwDocShell( SFX_CREATE_MODE_INTERNAL ));
1032 0 : SfxMedium* pWorkMed = new SfxMedium( sSourceDocumentURL, STREAM_STD_READ );
1033 0 : pWorkMed->SetFilter( pSfxFlt );
1034 :
1035 0 : if (xWorkDocSh->DoLoad(pWorkMed))
1036 : {
1037 : //create a view frame for the document
1038 0 : SfxViewFrame* pWorkFrame = SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 );
1039 : //request the layout calculation
1040 : SwWrtShell& rWorkShell =
1041 0 : static_cast< SwView* >(pWorkFrame->GetViewShell())->GetWrtShell();
1042 0 : rWorkShell.CalcLayout();
1043 0 : SwDoc* pWorkDoc = ((SwDocShell*)(&xWorkDocSh))->GetDoc();
1044 0 : SwNewDBMgr* pOldDBMgr = pWorkDoc->GetNewDBMgr();
1045 0 : pWorkDoc->SetNewDBMgr( this );
1046 0 : SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), xWorkDocSh));
1047 0 : pWorkDoc->UpdateFlds(NULL, false);
1048 0 : SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), xWorkDocSh));
1049 :
1050 0 : pWorkDoc->RemoveInvisibleContent();
1051 :
1052 : // launch MailMergeEvent if required
1053 0 : const SwXMailMerge *pEvtSrc = GetMailMergeEvtSrc();
1054 0 : if(pEvtSrc)
1055 : {
1056 0 : uno::Reference< XInterface > xRef( (XMailMergeBroadcaster *) pEvtSrc );
1057 0 : text::MailMergeEvent aEvt( xRef, xWorkDocSh->GetModel() );
1058 0 : pEvtSrc->LaunchMailMergeEvent( aEvt );
1059 : }
1060 :
1061 0 : if(rMergeDescriptor.bCreateSingleFile || bAsSingleFile )
1062 : {
1063 : OSL_ENSURE( pTargetShell, "no target shell available!" );
1064 : // copy created file into the target document
1065 0 : rWorkShell.ConvertFieldsToText();
1066 0 : rWorkShell.SetNumberingRestart();
1067 0 : if( bSynchronizedDoc )
1068 : {
1069 0 : lcl_RemoveSectionLinks( rWorkShell );
1070 : }
1071 :
1072 : // insert the document into the target document
1073 0 : rWorkShell.SttEndDoc(sal_False);
1074 0 : rWorkShell.SttEndDoc(sal_True);
1075 0 : rWorkShell.SelAll();
1076 0 : pTargetShell->SwCrsrShell::SttEndDoc( sal_False );
1077 : //#i72517# the headers and footers are still those from the source - update in case of fields inside header/footer
1078 0 : if( !nDocNo && bPageStylesWithHeaderFooter )
1079 0 : pTargetShell->GetView().GetDocShell()->_LoadStyles( *rWorkShell.GetView().GetDocShell(), sal_True );
1080 : //#i72517# put the styles to the target document
1081 : //if the source uses headers or footers each new copy need to copy a new page styles
1082 0 : if(bPageStylesWithHeaderFooter)
1083 : {
1084 : //create a new pagestyle
1085 : //copy the pagedesc from the current document to the new document and change the name of the to-be-applied style
1086 :
1087 0 : SwDoc* pTargetDoc = pTargetShell->GetDoc();
1088 0 : SwPageDesc* pSourcePageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
1089 0 : String sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo );
1090 0 : pTargetDoc->MakePageDesc( sNewPageDescName );
1091 0 : SwPageDesc* pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
1092 0 : if(pSourcePageDesc && pTargetPageDesc)
1093 : {
1094 0 : pTargetDoc->CopyPageDesc( *pSourcePageDesc, *pTargetPageDesc, false );
1095 0 : sModifiedStartingPageDesc = sNewPageDescName;
1096 0 : lcl_CopyFollowPageDesc( *pTargetShell, *pSourcePageDesc, *pTargetPageDesc, nDocNo );
1097 0 : }
1098 : }
1099 :
1100 0 : if(nDocNo > 1)
1101 0 : pTargetShell->InsertPageBreak( &sModifiedStartingPageDesc, nStartingPageNo );
1102 : else
1103 0 : pTargetShell->SetPageStyle(sModifiedStartingPageDesc);
1104 : OSL_ENSURE(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended");
1105 : //#i51359# add a second paragraph in case there's only one
1106 : {
1107 0 : SwNodeIndex aIdx( pWorkDoc->GetNodes().GetEndOfExtras(), 2 );
1108 0 : SwPosition aTestPos( aIdx );
1109 0 : SwCursor aTestCrsr(aTestPos,0,false);
1110 0 : if(!aTestCrsr.MovePara(fnParaNext, fnParaStart))
1111 : {
1112 : //append a paragraph
1113 0 : pWorkDoc->AppendTxtNode( aTestPos );
1114 0 : }
1115 : }
1116 0 : pTargetShell->Paste( rWorkShell.GetDoc(), sal_True );
1117 :
1118 : //convert fields in page styles (header/footer - has to be done after the first document has been pasted
1119 0 : if(1 == nDocNo)
1120 : {
1121 0 : pTargetShell->CalcLayout();
1122 0 : pTargetShell->ConvertFieldsToText();
1123 0 : }
1124 : }
1125 : else
1126 : {
1127 0 : String sFileURL = aTempFileURL.GetMainURL( INetURLObject::NO_DECODE );
1128 : SfxMedium* pDstMed = new SfxMedium(
1129 : sFileURL,
1130 0 : STREAM_STD_READWRITE );
1131 0 : pDstMed->SetFilter( pStoreToFilter );
1132 0 : if(pDstMed->GetItemSet())
1133 : {
1134 0 : if(pStoreToFilterOptions )
1135 0 : pDstMed->GetItemSet()->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, *pStoreToFilterOptions));
1136 0 : if(rMergeDescriptor.aSaveToFilterData.getLength())
1137 0 : pDstMed->GetItemSet()->Put(SfxUsrAnyItem(SID_FILTER_DATA, makeAny(rMergeDescriptor.aSaveToFilterData)));
1138 : }
1139 :
1140 : //convert fields to text if we are exporting to PDF
1141 : //this prevents a second merge while updating the fields in SwXTextDocument::getRendererCount()
1142 0 : if( pStoreToFilter && pStoreToFilter->GetFilterName().EqualsAscii("writer_pdf_Export"))
1143 0 : rWorkShell.ConvertFieldsToText();
1144 0 : xWorkDocSh->DoSaveAs(*pDstMed);
1145 0 : xWorkDocSh->DoSaveCompleted(pDstMed);
1146 0 : if( xWorkDocSh->GetError() )
1147 : {
1148 : // error message ??
1149 0 : ErrorHandler::HandleError( xWorkDocSh->GetError() );
1150 0 : bCancel = sal_True;
1151 0 : bLoop = sal_False;
1152 : }
1153 0 : if( bEMail )
1154 : {
1155 0 : SwDBFormatData aDBFormat;
1156 0 : aDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
1157 0 : aDBFormat.aNullDate = pImpl->pMergeData->aNullDate;
1158 0 : String sMailAddress = GetDBField( xColumnProp, aDBFormat);
1159 0 : if(!SwMailMergeHelper::CheckMailAddress( sMailAddress ))
1160 : {
1161 : OSL_FAIL("invalid e-Mail address in database column");
1162 : }
1163 : else
1164 : {
1165 0 : SwMailMessage* pMessage = new SwMailMessage;
1166 0 : uno::Reference< mail::XMailMessage > xMessage = pMessage;
1167 0 : if(rMergeDescriptor.pMailMergeConfigItem->IsMailReplyTo())
1168 0 : pMessage->setReplyToAddress(rMergeDescriptor.pMailMergeConfigItem->GetMailReplyTo());
1169 0 : pMessage->addRecipient( sMailAddress );
1170 0 : pMessage->SetSenderAddress( rMergeDescriptor.pMailMergeConfigItem->GetMailAddress() );
1171 0 : ::rtl::OUString sBody;
1172 0 : if(rMergeDescriptor.bSendAsAttachment)
1173 : {
1174 0 : sBody = rMergeDescriptor.sMailBody;
1175 0 : mail::MailAttachment aAttach;
1176 : aAttach.Data = new SwMailTransferable(
1177 : sFileURL,
1178 : rMergeDescriptor.sAttachmentName,
1179 0 : pStoreToFilter->GetMimeType());
1180 0 : aAttach.ReadableName = rMergeDescriptor.sAttachmentName;
1181 0 : pMessage->addAttachment( aAttach );
1182 : }
1183 : else
1184 : {
1185 : {
1186 : //read in the temporary file and use it as mail body
1187 0 : SfxMedium aMedium( sFileURL, STREAM_READ);
1188 0 : SvStream* pInStream = aMedium.GetInStream();
1189 : OSL_ENSURE(pInStream, "no output file created?");
1190 0 : if(pInStream)
1191 : {
1192 0 : pInStream->SetStreamCharSet( eEncoding );
1193 0 : rtl::OString sLine;
1194 0 : sal_Bool bDone = pInStream->ReadLine( sLine );
1195 0 : while ( bDone )
1196 : {
1197 0 : sBody += rtl::OStringToOUString(sLine, eEncoding);
1198 0 : sBody += ::rtl::OUString('\n');
1199 0 : bDone = pInStream->ReadLine( sLine );
1200 0 : }
1201 0 : }
1202 : }
1203 : }
1204 0 : pMessage->setSubject( rMergeDescriptor.sSubject );
1205 : uno::Reference< datatransfer::XTransferable> xBody =
1206 : new SwMailTransferable(
1207 : sBody,
1208 0 : sBodyMimeType);
1209 0 : pMessage->setBody( xBody );
1210 :
1211 0 : if(rMergeDescriptor.aCopiesTo.getLength())
1212 : {
1213 0 : const ::rtl::OUString* pCopies = rMergeDescriptor.aCopiesTo.getConstArray();
1214 0 : for( sal_Int32 nToken = 0; nToken < rMergeDescriptor.aCopiesTo.getLength(); ++nToken)
1215 0 : pMessage->addCcRecipient( pCopies[nToken] );
1216 : }
1217 0 : if(rMergeDescriptor.aBlindCopiesTo.getLength())
1218 : {
1219 0 : const ::rtl::OUString* pCopies = rMergeDescriptor.aBlindCopiesTo.getConstArray();
1220 0 : for( sal_Int32 nToken = 0; nToken < rMergeDescriptor.aBlindCopiesTo.getLength(); ++nToken)
1221 0 : pMessage->addBccRecipient( pCopies[nToken] );
1222 : }
1223 0 : xMailDispatcher->enqueueMailMessage( xMessage );
1224 0 : if(!xMailDispatcher->isStarted())
1225 0 : xMailDispatcher->start();
1226 : //schedule for removal
1227 0 : aFilesToRemove.push_back(sFileURL);
1228 0 : }
1229 0 : }
1230 : }
1231 0 : pWorkDoc->SetNewDBMgr( pOldDBMgr );
1232 : }
1233 0 : xWorkDocSh->DoClose();
1234 0 : }
1235 : }
1236 0 : nDocNo++;
1237 0 : nEndRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
1238 0 : } while( !bCancel &&
1239 0 : (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord()));
1240 :
1241 0 : aPrtMonDlg.Show( sal_False );
1242 :
1243 : // save the single output document
1244 0 : if(rMergeDescriptor.bCreateSingleFile || bAsSingleFile)
1245 : {
1246 0 : if( rMergeDescriptor.nMergeType != DBMGR_MERGE_MAILMERGE )
1247 : {
1248 : OSL_ENSURE( aTempFile.get(), "Temporary file not available" );
1249 0 : INetURLObject aTempFileURL(bAsSingleFile ? sSubject : aTempFile->GetURL());
1250 : SfxMedium* pDstMed = new SfxMedium(
1251 : aTempFileURL.GetMainURL( INetURLObject::NO_DECODE ),
1252 0 : STREAM_STD_READWRITE );
1253 0 : pDstMed->SetFilter( pStoreToFilter );
1254 0 : if(pDstMed->GetItemSet())
1255 : {
1256 0 : if(pStoreToFilterOptions )
1257 0 : pDstMed->GetItemSet()->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, *pStoreToFilterOptions));
1258 0 : if(rMergeDescriptor.aSaveToFilterData.getLength())
1259 0 : pDstMed->GetItemSet()->Put(SfxUsrAnyItem(SID_FILTER_DATA, makeAny(rMergeDescriptor.aSaveToFilterData)));
1260 : }
1261 :
1262 0 : xTargetDocShell->DoSaveAs(*pDstMed);
1263 0 : xTargetDocShell->DoSaveCompleted(pDstMed);
1264 0 : if( xTargetDocShell->GetError() )
1265 : {
1266 : // error message ??
1267 0 : ErrorHandler::HandleError( xTargetDocShell->GetError() );
1268 0 : bLoop = sal_False;
1269 0 : }
1270 : }
1271 0 : else if( pTargetView ) // must be available!
1272 : {
1273 : //print the target document
1274 : #if OSL_DEBUG_LEVEL > 1
1275 : sal_Bool _bVal;
1276 : sal_Int16 _nVal;
1277 : rtl::OUString _sVal;
1278 : const beans::PropertyValue* pDbgPrintOptions = rMergeDescriptor.aPrintOptions.getConstArray();
1279 : for( sal_Int32 nOption = 0; nOption < rMergeDescriptor.aPrintOptions.getLength(); ++nOption)
1280 : {
1281 : rtl::OUString aName( pDbgPrintOptions[nOption].Name );
1282 : uno::Any aVal( pDbgPrintOptions[nOption].Value );
1283 : aVal >>= _bVal;
1284 : aVal >>= _nVal;
1285 : aVal >>= _sVal;
1286 : }
1287 : #endif
1288 : // printing should be done synchronously otherwise the document
1289 : // might already become invalid during the process
1290 0 : uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions );
1291 0 : const sal_Int32 nOpts = aOptions.getLength();
1292 0 : aOptions.realloc( nOpts + 1 );
1293 0 : aOptions[ nOpts ].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Wait"));
1294 0 : aOptions[ nOpts ].Value <<= sal_True ;
1295 : // move print options
1296 0 : const beans::PropertyValue* pPrintOptions = rMergeDescriptor.aPrintOptions.getConstArray();
1297 0 : for( sal_Int32 nOption = 0; nOption < rMergeDescriptor.aPrintOptions.getLength(); ++nOption)
1298 : {
1299 0 : if( pPrintOptions[nOption].Name == "CopyCount" || pPrintOptions[nOption].Name == "FileName"
1300 0 : || pPrintOptions[nOption].Name == "Collate" || pPrintOptions[nOption].Name == "Pages"
1301 0 : || pPrintOptions[nOption].Name == "Wait" )
1302 : {
1303 0 : aOptions.realloc( nOpts + 1 );
1304 0 : aOptions[ nOpts ].Name = pPrintOptions[nOption].Name;
1305 0 : aOptions[ nOpts ].Value = pPrintOptions[nOption].Value ;
1306 : }
1307 : }
1308 :
1309 0 : pTargetView->ExecPrint( aOptions, IsMergeSilent(), rMergeDescriptor.bPrintAsync );
1310 : }
1311 0 : xTargetDocShell->DoClose();
1312 : }
1313 :
1314 : //remove the temporary files
1315 0 : ::std::vector<String>::iterator aFileIter;
1316 0 : for(aFileIter = aFilesToRemove.begin();
1317 0 : aFileIter != aFilesToRemove.end(); ++aFileIter)
1318 0 : SWUnoHelper::UCB_DeleteFile( *aFileIter );
1319 :
1320 : // unlock all dispatchers
1321 0 : pViewFrm = SfxViewFrame::GetFirst(pSourrceDocSh);
1322 0 : while (pViewFrm)
1323 : {
1324 0 : pViewFrm->GetDispatcher()->Lock(sal_False);
1325 0 : pViewFrm = SfxViewFrame::GetNext(*pViewFrm, pSourrceDocSh);
1326 : }
1327 :
1328 0 : SW_MOD()->SetView(&pSourceShell->GetView());
1329 : }
1330 :
1331 0 : nMergeType = DBMGR_INSERT;
1332 : }
1333 :
1334 0 : if(bEMail)
1335 : {
1336 0 : xMailDispatcher->stop();
1337 0 : xMailDispatcher->shutdown();
1338 :
1339 : }
1340 :
1341 0 : return bLoop;
1342 : }
1343 :
1344 0 : IMPL_LINK_INLINE_START( SwNewDBMgr, PrtCancelHdl, Button *, pButton )
1345 : {
1346 0 : pButton->GetParent()->Hide();
1347 0 : bCancel = sal_True;
1348 0 : return 0;
1349 : }
1350 0 : IMPL_LINK_INLINE_END( SwNewDBMgr, PrtCancelHdl, Button *, pButton )
1351 :
1352 : /*--------------------------------------------------------------------
1353 : Description: determine the column's Numberformat and transfer
1354 : to the forwarded Formatter, if applicable.
1355 : --------------------------------------------------------------------*/
1356 0 : sal_uLong SwNewDBMgr::GetColumnFmt( const String& rDBName,
1357 : const String& rTableName,
1358 : const String& rColNm,
1359 : SvNumberFormatter* pNFmtr,
1360 : long nLanguage )
1361 : {
1362 0 : sal_uLong nRet = 0;
1363 0 : if(pNFmtr)
1364 : {
1365 0 : uno::Reference< XDataSource> xSource;
1366 0 : uno::Reference< XConnection> xConnection;
1367 0 : sal_Bool bUseMergeData = sal_False;
1368 0 : uno::Reference< XColumnsSupplier> xColsSupp;
1369 0 : bool bDisposeConnection = false;
1370 0 : if(pImpl->pMergeData &&
1371 0 : pImpl->pMergeData->sDataSource.equals(rDBName) && pImpl->pMergeData->sCommand.equals(rTableName))
1372 : {
1373 0 : xConnection = pImpl->pMergeData->xConnection;
1374 0 : xSource = SwNewDBMgr::getDataSourceAsParent(xConnection,rDBName);
1375 0 : bUseMergeData = sal_True;
1376 0 : xColsSupp = xColsSupp.query( pImpl->pMergeData->xResultSet );
1377 : }
1378 0 : if(!xConnection.is())
1379 : {
1380 0 : SwDBData aData;
1381 0 : aData.sDataSource = rDBName;
1382 0 : aData.sCommand = rTableName;
1383 0 : aData.nCommandType = -1;
1384 0 : SwDSParam* pParam = FindDSData(aData, sal_False);
1385 0 : if(pParam && pParam->xConnection.is())
1386 : {
1387 0 : xConnection = pParam->xConnection;
1388 0 : xColsSupp = xColsSupp.query( pParam->xResultSet );
1389 : }
1390 : else
1391 : {
1392 0 : rtl::OUString sDBName(rDBName);
1393 0 : xConnection = RegisterConnection( sDBName );
1394 0 : bDisposeConnection = true;
1395 : }
1396 0 : if(bUseMergeData)
1397 0 : pImpl->pMergeData->xConnection = xConnection;
1398 : }
1399 0 : bool bDispose = !xColsSupp.is();
1400 0 : if(bDispose)
1401 : {
1402 0 : xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName);
1403 : }
1404 0 : if(xColsSupp.is())
1405 : {
1406 0 : uno::Reference<XNameAccess> xCols;
1407 : try
1408 : {
1409 0 : xCols = xColsSupp->getColumns();
1410 : }
1411 0 : catch(const Exception&)
1412 : {
1413 : OSL_FAIL("Exception in getColumns()");
1414 : }
1415 0 : if(!xCols.is() || !xCols->hasByName(rColNm))
1416 0 : return nRet;
1417 0 : Any aCol = xCols->getByName(rColNm);
1418 0 : uno::Reference< XPropertySet > xColumn;
1419 0 : aCol >>= xColumn;
1420 0 : nRet = GetColumnFmt(xSource, xConnection, xColumn, pNFmtr, nLanguage);
1421 0 : if(bDispose)
1422 : {
1423 0 : ::comphelper::disposeComponent( xColsSupp );
1424 : }
1425 0 : if(bDisposeConnection)
1426 : {
1427 0 : ::comphelper::disposeComponent( xConnection );
1428 0 : }
1429 : }
1430 : else
1431 0 : nRet = pNFmtr->GetFormatIndex( NF_NUMBER_STANDARD, LANGUAGE_SYSTEM );
1432 : }
1433 0 : return nRet;
1434 : }
1435 :
1436 0 : sal_uLong SwNewDBMgr::GetColumnFmt( uno::Reference< XDataSource> xSource,
1437 : uno::Reference< XConnection> xConnection,
1438 : uno::Reference< XPropertySet> xColumn,
1439 : SvNumberFormatter* pNFmtr,
1440 : long nLanguage )
1441 : {
1442 : // set the NumberFormat in the doc if applicable
1443 0 : sal_uLong nRet = 0;
1444 :
1445 0 : if(!xSource.is())
1446 : {
1447 0 : uno::Reference<XChild> xChild(xConnection, UNO_QUERY);
1448 0 : if ( xChild.is() )
1449 0 : xSource = uno::Reference<XDataSource>(xChild->getParent(), UNO_QUERY);
1450 : }
1451 0 : if(xSource.is() && xConnection.is() && xColumn.is() && pNFmtr)
1452 : {
1453 0 : SvNumberFormatsSupplierObj* pNumFmt = new SvNumberFormatsSupplierObj( pNFmtr );
1454 0 : uno::Reference< util::XNumberFormatsSupplier > xDocNumFmtsSupplier = pNumFmt;
1455 0 : uno::Reference< XNumberFormats > xDocNumberFormats = xDocNumFmtsSupplier->getNumberFormats();
1456 0 : uno::Reference< XNumberFormatTypes > xDocNumberFormatTypes(xDocNumberFormats, UNO_QUERY);
1457 :
1458 0 : com::sun::star::lang::Locale aLocale( LanguageTag( (LanguageType)nLanguage ).getLocale());
1459 :
1460 : //get the number formatter of the data source
1461 0 : uno::Reference<XPropertySet> xSourceProps(xSource, UNO_QUERY);
1462 0 : uno::Reference< XNumberFormats > xNumberFormats;
1463 0 : if(xSourceProps.is())
1464 : {
1465 0 : Any aFormats = xSourceProps->getPropertyValue("NumberFormatsSupplier");
1466 0 : if(aFormats.hasValue())
1467 : {
1468 0 : uno::Reference<XNumberFormatsSupplier> xSuppl;
1469 0 : aFormats >>= xSuppl;
1470 0 : if(xSuppl.is())
1471 : {
1472 0 : xNumberFormats = xSuppl->getNumberFormats();
1473 0 : }
1474 0 : }
1475 : }
1476 0 : bool bUseDefault = true;
1477 : try
1478 : {
1479 0 : Any aFormatKey = xColumn->getPropertyValue("FormatKey");
1480 0 : if(aFormatKey.hasValue())
1481 : {
1482 0 : sal_Int32 nFmt = 0;
1483 0 : aFormatKey >>= nFmt;
1484 0 : if(xNumberFormats.is())
1485 : {
1486 : try
1487 : {
1488 0 : uno::Reference<XPropertySet> xNumProps = xNumberFormats->getByKey( nFmt );
1489 0 : Any aFormatString = xNumProps->getPropertyValue("FormatString");
1490 0 : Any aLocaleVal = xNumProps->getPropertyValue("Locale");
1491 0 : rtl::OUString sFormat;
1492 0 : aFormatString >>= sFormat;
1493 0 : lang::Locale aLoc;
1494 0 : aLocaleVal >>= aLoc;
1495 0 : nFmt = xDocNumberFormats->queryKey( sFormat, aLoc, sal_False );
1496 0 : if(NUMBERFORMAT_ENTRY_NOT_FOUND == sal::static_int_cast< sal_uInt32, sal_Int32>(nFmt))
1497 0 : nFmt = xDocNumberFormats->addNew( sFormat, aLoc );
1498 0 : nRet = nFmt;
1499 0 : bUseDefault = false;
1500 : }
1501 0 : catch(const Exception&)
1502 : {
1503 : OSL_FAIL("illegal number format key");
1504 : }
1505 : }
1506 0 : }
1507 : }
1508 0 : catch(const Exception&)
1509 : {
1510 : OSL_FAIL("no FormatKey property found");
1511 : }
1512 0 : if(bUseDefault)
1513 0 : nRet = SwNewDBMgr::GetDbtoolsClient().getDefaultNumberFormat(xColumn, xDocNumberFormatTypes, aLocale);
1514 : }
1515 0 : return nRet;
1516 : }
1517 :
1518 0 : sal_Int32 SwNewDBMgr::GetColumnType( const String& rDBName,
1519 : const String& rTableName,
1520 : const String& rColNm )
1521 : {
1522 0 : sal_Int32 nRet = DataType::SQLNULL;
1523 0 : SwDBData aData;
1524 0 : aData.sDataSource = rDBName;
1525 0 : aData.sCommand = rTableName;
1526 0 : aData.nCommandType = -1;
1527 0 : SwDSParam* pParam = FindDSData(aData, sal_False);
1528 0 : uno::Reference< XConnection> xConnection;
1529 0 : uno::Reference< XColumnsSupplier > xColsSupp;
1530 0 : bool bDispose = false;
1531 0 : if(pParam && pParam->xConnection.is())
1532 : {
1533 0 : xConnection = pParam->xConnection;
1534 0 : xColsSupp = uno::Reference< XColumnsSupplier >( pParam->xResultSet, UNO_QUERY );
1535 : }
1536 : else
1537 : {
1538 0 : rtl::OUString sDBName(rDBName);
1539 0 : xConnection = RegisterConnection( sDBName );
1540 : }
1541 0 : if( !xColsSupp.is() )
1542 : {
1543 0 : xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName);
1544 0 : bDispose = true;
1545 : }
1546 0 : if(xColsSupp.is())
1547 : {
1548 0 : uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
1549 0 : if(xCols->hasByName(rColNm))
1550 : {
1551 0 : Any aCol = xCols->getByName(rColNm);
1552 0 : uno::Reference<XPropertySet> xCol;
1553 0 : aCol >>= xCol;
1554 0 : Any aType = xCol->getPropertyValue(rtl::OUString("Type"));
1555 0 : aType >>= nRet;
1556 : }
1557 0 : if(bDispose)
1558 0 : ::comphelper::disposeComponent( xColsSupp );
1559 : }
1560 0 : return nRet;
1561 : }
1562 :
1563 0 : uno::Reference< sdbc::XConnection> SwNewDBMgr::GetConnection(const String& rDataSource,
1564 : uno::Reference<XDataSource>& rxSource)
1565 : {
1566 0 : Reference< sdbc::XConnection> xConnection;
1567 0 : Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1568 : try
1569 : {
1570 0 : Reference<XCompletedConnection> xComplConnection(SwNewDBMgr::GetDbtoolsClient().getDataSource(rDataSource, xContext),UNO_QUERY);
1571 0 : if ( xComplConnection.is() )
1572 : {
1573 0 : rxSource.set(xComplConnection,UNO_QUERY);
1574 0 : Reference< XInteractionHandler > xHandler( InteractionHandler::createWithParent(xContext, 0), UNO_QUERY_THROW );
1575 0 : xConnection = xComplConnection->connectWithCompletion( xHandler );
1576 0 : }
1577 : }
1578 0 : catch(const Exception&)
1579 : {
1580 : }
1581 :
1582 0 : return xConnection;
1583 : }
1584 :
1585 0 : uno::Reference< sdbcx::XColumnsSupplier> SwNewDBMgr::GetColumnSupplier(uno::Reference<sdbc::XConnection> xConnection,
1586 : const String& rTableOrQuery,
1587 : sal_uInt8 eTableOrQuery)
1588 : {
1589 0 : Reference< sdbcx::XColumnsSupplier> xRet;
1590 : try
1591 : {
1592 0 : if(eTableOrQuery == SW_DB_SELECT_UNKNOWN)
1593 : {
1594 : //search for a table with the given command name
1595 0 : Reference<XTablesSupplier> xTSupplier = Reference<XTablesSupplier>(xConnection, UNO_QUERY);
1596 0 : if(xTSupplier.is())
1597 : {
1598 0 : Reference<XNameAccess> xTbls = xTSupplier->getTables();
1599 0 : eTableOrQuery = xTbls->hasByName(rTableOrQuery) ?
1600 0 : SW_DB_SELECT_TABLE : SW_DB_SELECT_QUERY;
1601 0 : }
1602 : }
1603 : sal_Int32 nCommandType = SW_DB_SELECT_TABLE == eTableOrQuery ?
1604 0 : CommandType::TABLE : CommandType::QUERY;
1605 0 : Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
1606 0 : Reference<XRowSet> xRowSet(xMgr->createInstance("com.sun.star.sdb.RowSet"), UNO_QUERY);
1607 :
1608 0 : ::rtl::OUString sDataSource;
1609 0 : Reference<XDataSource> xSource = SwNewDBMgr::getDataSourceAsParent(xConnection, sDataSource);
1610 0 : Reference<XPropertySet> xSourceProperties(xSource, UNO_QUERY);
1611 0 : if(xSourceProperties.is())
1612 : {
1613 0 : xSourceProperties->getPropertyValue("Name") >>= sDataSource;
1614 : }
1615 :
1616 0 : Reference<XPropertySet> xRowProperties(xRowSet, UNO_QUERY);
1617 0 : xRowProperties->setPropertyValue("DataSourceName", makeAny(sDataSource));
1618 0 : xRowProperties->setPropertyValue("Command", makeAny(::rtl::OUString(rTableOrQuery)));
1619 0 : xRowProperties->setPropertyValue("CommandType", makeAny(nCommandType));
1620 0 : xRowProperties->setPropertyValue("FetchSize", makeAny((sal_Int32)10));
1621 0 : xRowProperties->setPropertyValue("ActiveConnection", makeAny(xConnection));
1622 0 : xRowSet->execute();
1623 0 : xRet = Reference<XColumnsSupplier>( xRowSet, UNO_QUERY );
1624 : }
1625 0 : catch(const uno::Exception&)
1626 : {
1627 : OSL_FAIL("Exception in SwDBMgr::GetColumnSupplier");
1628 : }
1629 :
1630 0 : return xRet;
1631 : }
1632 :
1633 0 : String SwNewDBMgr::GetDBField(uno::Reference<XPropertySet> xColumnProps,
1634 : const SwDBFormatData& rDBFormatData,
1635 : double* pNumber)
1636 : {
1637 0 : uno::Reference< XColumn > xColumn(xColumnProps, UNO_QUERY);
1638 0 : String sRet;
1639 : OSL_ENSURE(xColumn.is(), "SwNewDBMgr::::ImportDBField: illegal arguments");
1640 0 : if(!xColumn.is())
1641 : return sRet;
1642 :
1643 0 : Any aType = xColumnProps->getPropertyValue("Type");
1644 0 : sal_Int32 eDataType = 0;
1645 0 : aType >>= eDataType;
1646 0 : switch(eDataType)
1647 : {
1648 : case DataType::CHAR:
1649 : case DataType::VARCHAR:
1650 : case DataType::LONGVARCHAR:
1651 : try
1652 : {
1653 0 : sRet = xColumn->getString();
1654 : }
1655 0 : catch(const SQLException&)
1656 : {
1657 : }
1658 0 : break;
1659 : case DataType::BIT:
1660 : case DataType::BOOLEAN:
1661 : case DataType::TINYINT:
1662 : case DataType::SMALLINT:
1663 : case DataType::INTEGER:
1664 : case DataType::BIGINT:
1665 : case DataType::FLOAT:
1666 : case DataType::REAL:
1667 : case DataType::DOUBLE:
1668 : case DataType::NUMERIC:
1669 : case DataType::DECIMAL:
1670 : case DataType::DATE:
1671 : case DataType::TIME:
1672 : case DataType::TIMESTAMP:
1673 : {
1674 :
1675 : try
1676 : {
1677 0 : SwDbtoolsClient& aClient = SwNewDBMgr::GetDbtoolsClient();
1678 : sRet = aClient.getFormattedValue(
1679 : xColumnProps,
1680 : rDBFormatData.xFormatter,
1681 : rDBFormatData.aLocale,
1682 0 : rDBFormatData.aNullDate);
1683 0 : if (pNumber)
1684 : {
1685 0 : double fVal = xColumn->getDouble();
1686 0 : if(!xColumn->wasNull())
1687 : {
1688 0 : *pNumber = fVal;
1689 : }
1690 : }
1691 : }
1692 0 : catch(const Exception&)
1693 : {
1694 : OSL_FAIL("exception caught");
1695 : }
1696 :
1697 : }
1698 0 : break;
1699 : }
1700 :
1701 0 : return sRet;
1702 : }
1703 :
1704 : // releases the merge data source table or query after merge is completed
1705 0 : void SwNewDBMgr::EndMerge()
1706 : {
1707 : OSL_ENSURE(bInMerge, "merge is not active");
1708 0 : bInMerge = sal_False;
1709 0 : delete pImpl->pMergeData;
1710 0 : pImpl->pMergeData = 0;
1711 0 : }
1712 :
1713 : // checks if a desired data source table or query is open
1714 0 : sal_Bool SwNewDBMgr::IsDataSourceOpen(const String& rDataSource,
1715 : const String& rTableOrQuery, sal_Bool bMergeOnly)
1716 : {
1717 0 : if(pImpl->pMergeData)
1718 : {
1719 0 : return !bMergeLock &&
1720 0 : ((rDataSource == (String)pImpl->pMergeData->sDataSource &&
1721 0 : rTableOrQuery == (String)pImpl->pMergeData->sCommand)
1722 0 : ||(!rDataSource.Len() && !rTableOrQuery.Len()))
1723 : &&
1724 0 : pImpl->pMergeData->xResultSet.is();
1725 : }
1726 0 : else if(!bMergeOnly)
1727 : {
1728 0 : SwDBData aData;
1729 0 : aData.sDataSource = rDataSource;
1730 0 : aData.sCommand = rTableOrQuery;
1731 0 : aData.nCommandType = -1;
1732 0 : SwDSParam* pFound = FindDSData(aData, sal_False);
1733 0 : return (pFound && pFound->xResultSet.is());
1734 : }
1735 0 : return sal_False;
1736 : }
1737 :
1738 : // read column data at a specified position
1739 0 : sal_Bool SwNewDBMgr::GetColumnCnt(const String& rSourceName, const String& rTableName,
1740 : const String& rColumnName, sal_uInt32 nAbsRecordId,
1741 : long nLanguage,
1742 : rtl::OUString& rResult, double* pNumber)
1743 : {
1744 0 : sal_Bool bRet = sal_False;
1745 0 : SwDSParam* pFound = 0;
1746 : //check if it's the merge data source
1747 0 : if(pImpl->pMergeData &&
1748 0 : rSourceName == (String)pImpl->pMergeData->sDataSource &&
1749 0 : rTableName == (String)pImpl->pMergeData->sCommand)
1750 : {
1751 0 : pFound = pImpl->pMergeData;
1752 : }
1753 : else
1754 : {
1755 0 : SwDBData aData;
1756 0 : aData.sDataSource = rSourceName;
1757 0 : aData.sCommand = rTableName;
1758 0 : aData.nCommandType = -1;
1759 0 : pFound = FindDSData(aData, sal_False);
1760 : }
1761 0 : if (!pFound)
1762 0 : return sal_False;
1763 : //check validity of supplied record Id
1764 0 : if(pFound->aSelection.getLength())
1765 : {
1766 : //the destination has to be an element of the selection
1767 0 : const Any* pSelection = pFound->aSelection.getConstArray();
1768 0 : sal_Bool bFound = sal_False;
1769 0 : for(sal_Int32 nPos = 0; !bFound && nPos < pFound->aSelection.getLength(); nPos++)
1770 : {
1771 0 : sal_Int32 nSelection = 0;
1772 0 : pSelection[nPos] >>= nSelection;
1773 0 : if(nSelection == static_cast<sal_Int32>(nAbsRecordId))
1774 0 : bFound = sal_True;
1775 : }
1776 0 : if(!bFound)
1777 0 : return sal_False;
1778 : }
1779 0 : if(pFound->xResultSet.is() && !pFound->bAfterSelection)
1780 : {
1781 0 : sal_Int32 nOldRow = 0;
1782 : try
1783 : {
1784 0 : nOldRow = pFound->xResultSet->getRow();
1785 : }
1786 0 : catch(const Exception&)
1787 : {
1788 0 : return sal_False;
1789 : }
1790 : //position to the desired index
1791 0 : sal_Bool bMove = sal_True;
1792 0 : if ( nOldRow != static_cast<sal_Int32>(nAbsRecordId) )
1793 0 : bMove = lcl_MoveAbsolute(pFound, nAbsRecordId);
1794 0 : if(bMove)
1795 : {
1796 0 : bRet = lcl_GetColumnCnt(pFound, rColumnName, nLanguage, rResult, pNumber);
1797 : }
1798 0 : if ( nOldRow != static_cast<sal_Int32>(nAbsRecordId) )
1799 0 : bMove = lcl_MoveAbsolute(pFound, nOldRow);
1800 : }
1801 0 : return bRet;
1802 : }
1803 :
1804 :
1805 : // reads the column data at the current position
1806 0 : sal_Bool SwNewDBMgr::GetMergeColumnCnt(const String& rColumnName, sal_uInt16 nLanguage,
1807 : rtl::OUString &rResult, double *pNumber, sal_uInt32 * /*pFormat*/)
1808 : {
1809 0 : if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is() || pImpl->pMergeData->bAfterSelection )
1810 : {
1811 0 : rResult = rtl::OUString();
1812 0 : return sal_False;
1813 : }
1814 :
1815 0 : sal_Bool bRet = lcl_GetColumnCnt(pImpl->pMergeData, rColumnName, nLanguage, rResult, pNumber);
1816 0 : return bRet;
1817 : }
1818 :
1819 0 : sal_Bool SwNewDBMgr::ToNextMergeRecord()
1820 : {
1821 : OSL_ENSURE(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge");
1822 0 : return ToNextRecord(pImpl->pMergeData);
1823 : }
1824 :
1825 0 : sal_Bool SwNewDBMgr::ToNextRecord(
1826 : const String& rDataSource, const String& rCommand, sal_Int32 /*nCommandType*/)
1827 : {
1828 0 : SwDSParam* pFound = 0;
1829 0 : if(pImpl->pMergeData &&
1830 0 : rDataSource == (String)pImpl->pMergeData->sDataSource &&
1831 0 : rCommand == (String)pImpl->pMergeData->sCommand)
1832 0 : pFound = pImpl->pMergeData;
1833 : else
1834 : {
1835 0 : SwDBData aData;
1836 0 : aData.sDataSource = rDataSource;
1837 0 : aData.sCommand = rCommand;
1838 0 : aData.nCommandType = -1;
1839 0 : pFound = FindDSData(aData, sal_False);
1840 : }
1841 0 : return ToNextRecord(pFound);
1842 : }
1843 :
1844 0 : sal_Bool SwNewDBMgr::ToNextRecord(SwDSParam* pParam)
1845 : {
1846 0 : sal_Bool bRet = sal_True;
1847 0 : if(!pParam || !pParam->xResultSet.is() || pParam->bEndOfDB ||
1848 0 : (pParam->aSelection.getLength() && pParam->aSelection.getLength() <= pParam->nSelectionIndex))
1849 : {
1850 0 : if(pParam)
1851 0 : pParam->CheckEndOfDB();
1852 0 : return sal_False;
1853 : }
1854 : try
1855 : {
1856 0 : if(pParam->aSelection.getLength())
1857 : {
1858 0 : sal_Int32 nPos = 0;
1859 0 : pParam->aSelection.getConstArray()[ pParam->nSelectionIndex++ ] >>= nPos;
1860 0 : pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos );
1861 0 : pParam->CheckEndOfDB();
1862 0 : bRet = !pParam->bEndOfDB;
1863 0 : if(pParam->nSelectionIndex >= pParam->aSelection.getLength())
1864 0 : pParam->bEndOfDB = sal_True;
1865 : }
1866 : else
1867 : {
1868 0 : sal_Int32 nBefore = pParam->xResultSet->getRow();
1869 0 : pParam->bEndOfDB = !pParam->xResultSet->next();
1870 0 : if( !pParam->bEndOfDB && nBefore == pParam->xResultSet->getRow())
1871 : {
1872 : //next returned true but it didn't move
1873 0 : pParam->bEndOfDB = sal_True;
1874 : }
1875 :
1876 0 : pParam->CheckEndOfDB();
1877 0 : bRet = !pParam->bEndOfDB;
1878 0 : ++pParam->nSelectionIndex;
1879 : }
1880 : }
1881 0 : catch(const Exception&)
1882 : {
1883 : }
1884 0 : return bRet;
1885 : }
1886 :
1887 : /* ------------------------------------------------------------------------
1888 : synchronized labels contain a next record field at their end
1889 : to assure that the next page can be created in mail merge
1890 : the cursor position must be validated
1891 : ---------------------------------------------------------------------------*/
1892 0 : sal_Bool SwNewDBMgr::ExistsNextRecord() const
1893 : {
1894 0 : return pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB;
1895 : }
1896 :
1897 0 : sal_uInt32 SwNewDBMgr::GetSelectedRecordId()
1898 : {
1899 0 : sal_uInt32 nRet = 0;
1900 : OSL_ENSURE(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge");
1901 0 : if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is())
1902 0 : return sal_False;
1903 : try
1904 : {
1905 0 : nRet = pImpl->pMergeData->xResultSet->getRow();
1906 : }
1907 0 : catch(const Exception&)
1908 : {
1909 : }
1910 0 : return nRet;
1911 : }
1912 :
1913 0 : sal_Bool SwNewDBMgr::ToRecordId(sal_Int32 nSet)
1914 : {
1915 : OSL_ENSURE(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge");
1916 0 : if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is()|| nSet < 0)
1917 0 : return sal_False;
1918 0 : sal_Bool bRet = sal_False;
1919 0 : sal_Int32 nAbsPos = nSet;
1920 :
1921 0 : if(nAbsPos >= 0)
1922 : {
1923 0 : bRet = lcl_MoveAbsolute(pImpl->pMergeData, nAbsPos);
1924 0 : pImpl->pMergeData->bEndOfDB = !bRet;
1925 0 : pImpl->pMergeData->CheckEndOfDB();
1926 : }
1927 0 : return bRet;
1928 : }
1929 :
1930 0 : sal_Bool SwNewDBMgr::OpenDataSource(const String& rDataSource, const String& rTableOrQuery,
1931 : sal_Int32 nCommandType, bool bCreate)
1932 : {
1933 0 : SwDBData aData;
1934 0 : aData.sDataSource = rDataSource;
1935 0 : aData.sCommand = rTableOrQuery;
1936 0 : aData.nCommandType = nCommandType;
1937 :
1938 0 : SwDSParam* pFound = FindDSData(aData, sal_True);
1939 0 : uno::Reference< XDataSource> xSource;
1940 0 : if(pFound->xResultSet.is())
1941 0 : return sal_True;
1942 0 : SwDSParam* pParam = FindDSConnection(rDataSource, sal_False);
1943 0 : uno::Reference< XConnection> xConnection;
1944 0 : if(pParam && pParam->xConnection.is())
1945 0 : pFound->xConnection = pParam->xConnection;
1946 0 : else if(bCreate)
1947 : {
1948 0 : rtl::OUString sDataSource(rDataSource);
1949 0 : pFound->xConnection = RegisterConnection( sDataSource );
1950 : }
1951 0 : if(pFound->xConnection.is())
1952 : {
1953 : try
1954 : {
1955 0 : uno::Reference< sdbc::XDatabaseMetaData > xMetaData = pFound->xConnection->getMetaData();
1956 : try
1957 : {
1958 : pFound->bScrollable = xMetaData
1959 0 : ->supportsResultSetType((sal_Int32)ResultSetType::SCROLL_INSENSITIVE);
1960 : }
1961 0 : catch(const Exception&)
1962 : {
1963 : // DB driver may not be ODBC 3.0 compliant
1964 0 : pFound->bScrollable = sal_True;
1965 : }
1966 0 : pFound->xStatement = pFound->xConnection->createStatement();
1967 0 : rtl::OUString aQuoteChar = xMetaData->getIdentifierQuoteString();
1968 0 : rtl::OUString sStatement("SELECT * FROM ");
1969 0 : sStatement = "SELECT * FROM ";
1970 0 : sStatement += aQuoteChar;
1971 0 : sStatement += rTableOrQuery;
1972 0 : sStatement += aQuoteChar;
1973 0 : pFound->xResultSet = pFound->xStatement->executeQuery( sStatement );
1974 :
1975 : //after executeQuery the cursor must be positioned
1976 0 : pFound->bEndOfDB = !pFound->xResultSet->next();
1977 0 : pFound->bAfterSelection = sal_False;
1978 0 : pFound->CheckEndOfDB();
1979 0 : ++pFound->nSelectionIndex;
1980 : }
1981 0 : catch (const Exception&)
1982 : {
1983 0 : pFound->xResultSet = 0;
1984 0 : pFound->xStatement = 0;
1985 0 : pFound->xConnection = 0;
1986 : }
1987 : }
1988 0 : return pFound->xResultSet.is();
1989 : }
1990 :
1991 0 : uno::Reference< XConnection> SwNewDBMgr::RegisterConnection(rtl::OUString& rDataSource)
1992 : {
1993 0 : SwDSParam* pFound = SwNewDBMgr::FindDSConnection(rDataSource, sal_True);
1994 0 : uno::Reference< XDataSource> xSource;
1995 0 : if(!pFound->xConnection.is())
1996 : {
1997 0 : pFound->xConnection = SwNewDBMgr::GetConnection(rDataSource, xSource );
1998 : try
1999 : {
2000 0 : uno::Reference<XComponent> xComponent(pFound->xConnection, UNO_QUERY);
2001 0 : if(xComponent.is())
2002 0 : xComponent->addEventListener(pImpl->xDisposeListener);
2003 : }
2004 0 : catch(const Exception&)
2005 : {
2006 : }
2007 : }
2008 0 : return pFound->xConnection;
2009 : }
2010 :
2011 0 : sal_uInt32 SwNewDBMgr::GetSelectedRecordId(
2012 : const String& rDataSource, const String& rTableOrQuery, sal_Int32 nCommandType)
2013 : {
2014 0 : sal_uInt32 nRet = 0xffffffff;
2015 : //check for merge data source first
2016 0 : if(pImpl->pMergeData && rDataSource == (String)pImpl->pMergeData->sDataSource &&
2017 0 : rTableOrQuery == (String)pImpl->pMergeData->sCommand &&
2018 : (nCommandType == -1 || nCommandType == pImpl->pMergeData->nCommandType) &&
2019 0 : pImpl->pMergeData->xResultSet.is())
2020 0 : nRet = GetSelectedRecordId();
2021 : else
2022 : {
2023 0 : SwDBData aData;
2024 0 : aData.sDataSource = rDataSource;
2025 0 : aData.sCommand = rTableOrQuery;
2026 0 : aData.nCommandType = nCommandType;
2027 0 : SwDSParam* pFound = FindDSData(aData, sal_False);
2028 0 : if(pFound && pFound->xResultSet.is())
2029 : {
2030 : try
2031 : { //if a selection array is set the current row at the result set may not be set yet
2032 0 : if(pFound->aSelection.getLength())
2033 : {
2034 0 : sal_Int32 nSelIndex = pFound->nSelectionIndex;
2035 0 : if(nSelIndex >= pFound->aSelection.getLength())
2036 0 : nSelIndex = pFound->aSelection.getLength() -1;
2037 0 : pFound->aSelection.getConstArray()[nSelIndex] >>= nRet;
2038 :
2039 : }
2040 : else
2041 0 : nRet = pFound->xResultSet->getRow();
2042 : }
2043 0 : catch(const Exception&)
2044 : {
2045 : }
2046 0 : }
2047 : }
2048 0 : return nRet;
2049 : }
2050 :
2051 :
2052 : // close all data sources - after fields were updated
2053 2 : void SwNewDBMgr::CloseAll(sal_Bool bIncludingMerge)
2054 : {
2055 : //the only thing done here is to reset the selection index
2056 : //all connections stay open
2057 2 : for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.size(); nPos++)
2058 : {
2059 0 : SwDSParam* pParam = &aDataSourceParams[nPos];
2060 0 : if(bIncludingMerge || pParam != pImpl->pMergeData)
2061 : {
2062 0 : pParam->nSelectionIndex = 0;
2063 0 : pParam->bAfterSelection = sal_False;
2064 0 : pParam->bEndOfDB = sal_False;
2065 : try
2066 : {
2067 0 : if(!bInMerge && pParam->xResultSet.is())
2068 0 : pParam->xResultSet->first();
2069 : }
2070 0 : catch(const Exception&)
2071 : {}
2072 : }
2073 : }
2074 2 : }
2075 :
2076 0 : SwDSParam* SwNewDBMgr::FindDSData(const SwDBData& rData, sal_Bool bCreate)
2077 : {
2078 : //prefer merge data if available
2079 0 : if(pImpl->pMergeData && rData.sDataSource == pImpl->pMergeData->sDataSource &&
2080 0 : rData.sCommand == pImpl->pMergeData->sCommand &&
2081 : (rData.nCommandType == -1 || rData.nCommandType == pImpl->pMergeData->nCommandType ||
2082 : (bCreate && pImpl->pMergeData->nCommandType == -1)))
2083 : {
2084 0 : return pImpl->pMergeData;
2085 : }
2086 :
2087 0 : SwDSParam* pFound = 0;
2088 0 : for(sal_uInt16 nPos = aDataSourceParams.size(); nPos; nPos--)
2089 : {
2090 0 : SwDSParam* pParam = &aDataSourceParams[nPos - 1];
2091 0 : if(rData.sDataSource == pParam->sDataSource &&
2092 0 : rData.sCommand == pParam->sCommand &&
2093 : (rData.nCommandType == -1 || rData.nCommandType == pParam->nCommandType ||
2094 : (bCreate && pParam->nCommandType == -1)))
2095 : {
2096 : // calls from the calculator may add a connection with an invalid commandtype
2097 : //later added "real" data base connections have to re-use the already available
2098 : //DSData and set the correct CommandType
2099 0 : if(bCreate && pParam->nCommandType == -1)
2100 0 : pParam->nCommandType = rData.nCommandType;
2101 0 : pFound = pParam;
2102 0 : break;
2103 : }
2104 : }
2105 0 : if(bCreate)
2106 : {
2107 0 : if(!pFound)
2108 : {
2109 0 : pFound = new SwDSParam(rData);
2110 0 : aDataSourceParams.push_back(pFound);
2111 : try
2112 : {
2113 0 : uno::Reference<XComponent> xComponent(pFound->xConnection, UNO_QUERY);
2114 0 : if(xComponent.is())
2115 0 : xComponent->addEventListener(pImpl->xDisposeListener);
2116 : }
2117 0 : catch(const Exception&)
2118 : {
2119 : }
2120 : }
2121 : }
2122 0 : return pFound;
2123 : }
2124 :
2125 0 : SwDSParam* SwNewDBMgr::FindDSConnection(const rtl::OUString& rDataSource, sal_Bool bCreate)
2126 : {
2127 : //prefer merge data if available
2128 0 : if(pImpl->pMergeData && rDataSource == pImpl->pMergeData->sDataSource )
2129 : {
2130 0 : return pImpl->pMergeData;
2131 : }
2132 0 : SwDSParam* pFound = 0;
2133 0 : for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.size(); nPos++)
2134 : {
2135 0 : SwDSParam* pParam = &aDataSourceParams[nPos];
2136 0 : if(rDataSource == pParam->sDataSource)
2137 : {
2138 0 : pFound = pParam;
2139 0 : break;
2140 : }
2141 : }
2142 0 : if(bCreate && !pFound)
2143 : {
2144 0 : SwDBData aData;
2145 0 : aData.sDataSource = rDataSource;
2146 0 : pFound = new SwDSParam(aData);
2147 0 : aDataSourceParams.push_back(pFound);
2148 : try
2149 : {
2150 0 : uno::Reference<XComponent> xComponent(pFound->xConnection, UNO_QUERY);
2151 0 : if(xComponent.is())
2152 0 : xComponent->addEventListener(pImpl->xDisposeListener);
2153 : }
2154 0 : catch(const Exception&)
2155 : {
2156 0 : }
2157 : }
2158 0 : return pFound;
2159 : }
2160 :
2161 58 : const SwDBData& SwNewDBMgr::GetAddressDBName()
2162 : {
2163 58 : return SW_MOD()->GetDBConfig()->GetAddressSource();
2164 : }
2165 :
2166 0 : Sequence<rtl::OUString> SwNewDBMgr::GetExistingDatabaseNames()
2167 : {
2168 0 : Reference<XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
2169 0 : Reference<XDatabaseContext> xDBContext = DatabaseContext::create(xContext);
2170 0 : return xDBContext->getElementNames();
2171 : }
2172 :
2173 0 : String SwNewDBMgr::LoadAndRegisterDataSource()
2174 : {
2175 0 : sfx2::FileDialogHelper aDlgHelper( TemplateDescription::FILEOPEN_SIMPLE, 0 );
2176 0 : Reference < XFilePicker > xFP = aDlgHelper.GetFilePicker();
2177 :
2178 0 : String sHomePath(SvtPathOptions().GetWorkPath());
2179 0 : aDlgHelper.SetDisplayDirectory( sHomePath );
2180 :
2181 0 : Reference<XFilterManager> xFltMgr(xFP, UNO_QUERY);
2182 :
2183 0 : String sFilterAll(SW_RES(STR_FILTER_ALL));
2184 0 : String sFilterAllData(SW_RES(STR_FILTER_ALL_DATA));
2185 0 : String sFilterSXB(SW_RES(STR_FILTER_SXB));
2186 0 : String sFilterSXC(SW_RES(STR_FILTER_SXC));
2187 0 : String sFilterDBF(SW_RES(STR_FILTER_DBF));
2188 0 : String sFilterXLS(SW_RES(STR_FILTER_XLS));
2189 0 : String sFilterTXT(SW_RES(STR_FILTER_TXT));
2190 0 : String sFilterCSV(SW_RES(STR_FILTER_CSV));
2191 : #ifdef WNT
2192 : String sFilterMDB(SW_RES(STR_FILTER_MDB));
2193 : String sFilterACCDB(SW_RES(STR_FILTER_ACCDB));
2194 : #endif
2195 0 : xFltMgr->appendFilter( sFilterAll, "*" );
2196 0 : xFltMgr->appendFilter( sFilterAllData, "*.ods;*.sxc;*.dbf;*.xls;*.txt;*.csv");
2197 :
2198 0 : xFltMgr->appendFilter( sFilterSXB, "*.odb" );
2199 0 : xFltMgr->appendFilter( sFilterSXC, "*.ods;*.sxc" );
2200 0 : xFltMgr->appendFilter( sFilterDBF, "*.dbf" );
2201 0 : xFltMgr->appendFilter( sFilterXLS, "*.xls" );
2202 0 : xFltMgr->appendFilter( sFilterTXT, "*.txt" );
2203 0 : xFltMgr->appendFilter( sFilterCSV, "*.csv" );
2204 : #ifdef WNT
2205 : xFltMgr->appendFilter( sFilterMDB, "*.mdb" );
2206 : xFltMgr->appendFilter( sFilterACCDB, "*.accdb" );
2207 : #endif
2208 :
2209 0 : xFltMgr->setCurrentFilter( sFilterAll ) ;
2210 0 : String sFind;
2211 0 : bool bTextConnection = false;
2212 0 : if( ERRCODE_NONE == aDlgHelper.Execute() )
2213 : {
2214 0 : String sURL = xFP->getFiles().getConstArray()[0];
2215 : //data sources have to be registered depending on their extensions
2216 0 : INetURLObject aURL( sURL );
2217 0 : String sExt( aURL.GetExtension() );
2218 0 : Any aURLAny;
2219 0 : Any aTableFilterAny;
2220 0 : Any aSuppressVersionsAny;
2221 0 : Any aInfoAny;
2222 0 : INetURLObject aTempURL(aURL);
2223 0 : bool bStore = true;
2224 0 : if(sExt.EqualsAscii("odb"))
2225 : {
2226 0 : bStore = false;
2227 : }
2228 0 : else if(sExt.EqualsIgnoreCaseAscii("sxc")
2229 0 : || sExt.EqualsIgnoreCaseAscii("ods")
2230 0 : || sExt.EqualsIgnoreCaseAscii("xls"))
2231 : {
2232 0 : rtl::OUString sDBURL("sdbc:calc:");
2233 0 : sDBURL += aTempURL.GetMainURL(INetURLObject::NO_DECODE);
2234 0 : aURLAny <<= sDBURL;
2235 : }
2236 0 : else if(sExt.EqualsIgnoreCaseAscii("dbf"))
2237 : {
2238 0 : aTempURL.removeSegment();
2239 0 : aTempURL.removeFinalSlash();
2240 0 : rtl::OUString sDBURL("sdbc:dbase:");
2241 0 : sDBURL += aTempURL.GetMainURL(INetURLObject::NO_DECODE);
2242 0 : aURLAny <<= sDBURL;
2243 : //set the filter to the file name without extension
2244 0 : Sequence<rtl::OUString> aFilters(1);
2245 0 : aFilters[0] = aURL.getBase();
2246 0 : aTableFilterAny <<= aFilters;
2247 : }
2248 0 : else if(sExt.EqualsIgnoreCaseAscii("csv") || sExt.EqualsIgnoreCaseAscii("txt"))
2249 : {
2250 0 : aTempURL.removeSegment();
2251 0 : aTempURL.removeFinalSlash();
2252 0 : rtl::OUString sDBURL("sdbc:flat:");
2253 : //only the 'path' has to be added
2254 0 : sDBURL += aTempURL.GetMainURL(INetURLObject::NO_DECODE);
2255 0 : aURLAny <<= sDBURL;
2256 :
2257 0 : bTextConnection = true;
2258 : //set the filter to the file name without extension
2259 0 : Sequence<rtl::OUString> aFilters(1);
2260 0 : aFilters[0] = aURL.getBase();
2261 0 : aTableFilterAny <<= aFilters;
2262 : }
2263 : #ifdef WNT
2264 : else if(sExt.EqualsIgnoreCaseAscii("mdb"))
2265 : {
2266 : rtl::OUString sDBURL("sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=");
2267 : sDBURL += aTempURL.PathToFileName();
2268 : aURLAny <<= sDBURL;
2269 : aSuppressVersionsAny <<= makeAny(true);
2270 : }
2271 : else if(sExt.EqualsIgnoreCaseAscii("accdb"))
2272 : {
2273 : rtl::OUString sDBURL("sdbc:ado:PROVIDER=Microsoft.ACE.OLEDB.12.0;DATA SOURCE=");
2274 : sDBURL += aTempURL.PathToFileName();
2275 : aURLAny <<= sDBURL;
2276 : aSuppressVersionsAny <<= makeAny(true);
2277 : }
2278 : #endif
2279 : try
2280 : {
2281 0 : Reference<XMultiServiceFactory> xMgr( ::comphelper::getProcessServiceFactory() );
2282 0 : Reference<XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
2283 0 : Reference<XDatabaseContext> xDBContext = DatabaseContext::create(xContext);
2284 0 : Reference<XSingleServiceFactory> xFact( xDBContext, UNO_QUERY);
2285 :
2286 : String sNewName = INetURLObject::decode( aURL.getName(),
2287 : INET_HEX_ESCAPE,
2288 : INetURLObject::DECODE_UNAMBIGUOUS,
2289 0 : RTL_TEXTENCODING_UTF8 );
2290 0 : xub_StrLen nExtLen = static_cast< xub_StrLen >(aURL.GetExtension().getLength());
2291 0 : sNewName.Erase( sNewName.Len() - nExtLen - 1, nExtLen + 1 );
2292 :
2293 : //find a unique name if sNewName already exists
2294 0 : sFind = sNewName;
2295 0 : sal_Int32 nIndex = 0;
2296 0 : while(xDBContext->hasByName(sFind))
2297 : {
2298 0 : sFind = sNewName;
2299 0 : sFind += String::CreateFromInt32(++nIndex);
2300 : }
2301 :
2302 0 : Reference<XInterface> xNewInstance;
2303 0 : if(!bStore)
2304 : {
2305 : //odb-file
2306 0 : Any aDataSource = xDBContext->getByName(aTempURL.GetMainURL(INetURLObject::NO_DECODE));
2307 0 : aDataSource >>= xNewInstance;
2308 : }
2309 : else
2310 : {
2311 0 : xNewInstance = xFact->createInstance();
2312 0 : Reference<XPropertySet> xDataProperties(xNewInstance, UNO_QUERY);
2313 :
2314 0 : if(aURLAny.hasValue())
2315 0 : xDataProperties->setPropertyValue("URL", aURLAny);
2316 0 : if(aTableFilterAny.hasValue())
2317 0 : xDataProperties->setPropertyValue("TableFilter", aTableFilterAny);
2318 0 : if(aSuppressVersionsAny.hasValue())
2319 0 : xDataProperties->setPropertyValue("SuppressVersionColumns", aSuppressVersionsAny);
2320 0 : if(aInfoAny.hasValue())
2321 0 : xDataProperties->setPropertyValue("Info", aInfoAny);
2322 :
2323 0 : if( bTextConnection )
2324 : {
2325 0 : uno::Reference < ui::dialogs::XExecutableDialog > xSettingsDlg(xMgr->createInstance( "com.sun.star.sdb.TextConnectionSettings" ), uno::UNO_QUERY);
2326 0 : if( xSettingsDlg->execute() )
2327 : {
2328 0 : uno::Any aSettings = xDataProperties->getPropertyValue( "Settings" );
2329 0 : uno::Reference < beans::XPropertySet > xDSSettings;
2330 0 : aSettings >>= xDSSettings;
2331 : ::comphelper::copyProperties(
2332 : uno::Reference < beans::XPropertySet >( xSettingsDlg, uno::UNO_QUERY ),
2333 0 : xDSSettings );
2334 0 : xDSSettings->setPropertyValue( "Extension", uno::makeAny( ::rtl::OUString( sExt )));
2335 0 : }
2336 : }
2337 :
2338 0 : Reference<XDocumentDataSource> xDS(xNewInstance, UNO_QUERY_THROW);
2339 0 : Reference<XStorable> xStore(xDS->getDatabaseDocument(), UNO_QUERY_THROW);
2340 0 : String sOutputExt = rtl::OUString(".odb");
2341 0 : String sTmpName;
2342 : {
2343 0 : utl::TempFile aTempFile(sNewName , &sOutputExt, &sHomePath);
2344 0 : aTempFile.EnableKillingFile(sal_True);
2345 0 : sTmpName = aTempFile.GetURL();
2346 : }
2347 0 : xStore->storeAsURL(sTmpName, Sequence< PropertyValue >());
2348 : }
2349 0 : Reference<XNamingService> xNaming(xDBContext, UNO_QUERY);
2350 0 : xNaming->registerObject( sFind, xNewInstance );
2351 :
2352 : }
2353 0 : catch(const Exception&)
2354 : {
2355 0 : }
2356 : }
2357 0 : return sFind;
2358 :
2359 : }
2360 :
2361 0 : void SwNewDBMgr::ExecuteFormLetter( SwWrtShell& rSh,
2362 : const Sequence<PropertyValue>& rProperties,
2363 : sal_Bool bWithDataSourceBrowser)
2364 : {
2365 : //prevent second call
2366 0 : if(pImpl->pMergeDialog)
2367 : return ;
2368 0 : rtl::OUString sDataSource, sDataTableOrQuery;
2369 0 : Sequence<Any> aSelection;
2370 :
2371 0 : sal_Int32 nCmdType = CommandType::TABLE;
2372 0 : uno::Reference< XConnection> xConnection;
2373 :
2374 0 : ODataAccessDescriptor aDescriptor(rProperties);
2375 0 : sDataSource = aDescriptor.getDataSource();
2376 0 : OSL_VERIFY(aDescriptor[daCommand] >>= sDataTableOrQuery);
2377 0 : OSL_VERIFY(aDescriptor[daCommandType] >>= nCmdType);
2378 :
2379 0 : if ( aDescriptor.has(daSelection) )
2380 0 : aDescriptor[daSelection] >>= aSelection;
2381 0 : if ( aDescriptor.has(daConnection) )
2382 0 : aDescriptor[daConnection] >>= xConnection;
2383 :
2384 0 : if(sDataSource.isEmpty() || sDataTableOrQuery.isEmpty())
2385 : {
2386 : OSL_FAIL("PropertyValues missing or unset");
2387 : return;
2388 : }
2389 :
2390 : //always create a connection for the dialog and dispose it after the dialog has been closed
2391 0 : SwDSParam* pFound = 0;
2392 0 : if(!xConnection.is())
2393 : {
2394 0 : xConnection = SwNewDBMgr::RegisterConnection(sDataSource);
2395 0 : pFound = FindDSConnection(sDataSource, sal_True);
2396 : }
2397 0 : SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2398 : OSL_ENSURE(pFact, "Dialogdiet fail!");
2399 : pImpl->pMergeDialog = pFact->CreateMailMergeDlg( DLG_MAILMERGE,
2400 0 : &rSh.GetView().GetViewFrame()->GetWindow(), rSh,
2401 : sDataSource,
2402 : sDataTableOrQuery,
2403 : nCmdType,
2404 : xConnection,
2405 0 : bWithDataSourceBrowser ? 0 : &aSelection);
2406 : OSL_ENSURE(pImpl->pMergeDialog, "Dialogdiet fail!");
2407 0 : if(pImpl->pMergeDialog->Execute() == RET_OK)
2408 : {
2409 0 : aDescriptor[daSelection] <<= pImpl->pMergeDialog->GetSelection();
2410 :
2411 0 : uno::Reference<XResultSet> xResSet = pImpl->pMergeDialog->GetResultSet();
2412 0 : if(xResSet.is())
2413 0 : aDescriptor[daCursor] <<= xResSet;
2414 :
2415 : // SfxObjectShellRef is ok, since there should be no control over the document lifetime here
2416 0 : SfxObjectShellRef xDocShell = rSh.GetView().GetViewFrame()->GetObjectShell();
2417 0 : SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE), xDocShell));
2418 : {
2419 : //copy rSh to aTempFile
2420 0 : ::rtl::OUString sTempURL;
2421 : const SfxFilter *pSfxFlt = SwIoSystem::GetFilterOfFormat(
2422 : rtl::OUString(FILTER_XML),
2423 0 : SwDocShell::Factory().GetFilterContainer() );
2424 : try
2425 : {
2426 :
2427 0 : uno::Sequence< beans::PropertyValue > aValues(1);
2428 0 : beans::PropertyValue* pValues = aValues.getArray();
2429 0 : pValues[0].Name = "FilterName";
2430 0 : pValues[0].Value <<= ::rtl::OUString(pSfxFlt->GetFilterName());
2431 0 : uno::Reference< XStorable > xStore( xDocShell->GetModel(), uno::UNO_QUERY);
2432 0 : sTempURL = URIHelper::SmartRel2Abs( INetURLObject(), utl::TempFile::CreateTempName() );
2433 0 : xStore->storeToURL( sTempURL, aValues );
2434 : }
2435 0 : catch(const uno::Exception&)
2436 : {
2437 : }
2438 0 : if( xDocShell->GetError() )
2439 : {
2440 : // error message ??
2441 0 : ErrorHandler::HandleError( xDocShell->GetError() );
2442 : }
2443 : else
2444 : {
2445 : // the shell will be explicitly closed, but it is more safe to use SfxObjectShellLock here
2446 : // especially for the case that the loading has failed
2447 0 : SfxObjectShellLock xWorkDocSh( new SwDocShell( SFX_CREATE_MODE_INTERNAL ));
2448 0 : SfxMedium* pWorkMed = new SfxMedium( sTempURL, STREAM_STD_READ );
2449 0 : pWorkMed->SetFilter( pSfxFlt );
2450 0 : if( xWorkDocSh->DoLoad(pWorkMed) )
2451 : {
2452 0 : SfxViewFrame *pFrame = SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 );
2453 0 : SwView *pView = (SwView*) pFrame->GetViewShell();
2454 0 : pView->AttrChangedNotify( &pView->GetWrtShell() );// in order for SelectShell to be called
2455 : //set the current DBMgr
2456 0 : SwDoc* pWorkDoc = pView->GetWrtShell().GetDoc();
2457 0 : SwNewDBMgr* pWorkDBMgr = pWorkDoc->GetNewDBMgr();
2458 0 : pWorkDoc->SetNewDBMgr( this );
2459 :
2460 0 : SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), pView->GetWrtShell(), aDescriptor );
2461 0 : aMergeDesc.sSaveToFilter = pImpl->pMergeDialog->GetSaveFilter();
2462 0 : aMergeDesc.bCreateSingleFile = !pImpl->pMergeDialog->IsSaveIndividualDocs();
2463 0 : if( !aMergeDesc.bCreateSingleFile && pImpl->pMergeDialog->IsGenerateFromDataBase() )
2464 : {
2465 0 : aMergeDesc.sAddressFromColumn = pImpl->pMergeDialog->GetColumnName();
2466 0 : aMergeDesc.sSubject = pImpl->pMergeDialog->GetPath();
2467 : }
2468 :
2469 0 : MergeNew(aMergeDesc);
2470 :
2471 0 : pWorkDoc->SetNewDBMgr( pWorkDBMgr );
2472 : //close the temporary file
2473 0 : uno::Reference< util::XCloseable > xClose( xWorkDocSh->GetModel(), uno::UNO_QUERY );
2474 0 : if (xClose.is())
2475 : {
2476 : try
2477 : {
2478 : //! 'sal_True' -> transfer ownership to vetoing object if vetoed!
2479 : //! I.e. now that object is responsible for closing the model and doc shell.
2480 0 : xClose->close( sal_True );
2481 : }
2482 0 : catch (const uno::Exception&)
2483 : {
2484 : }
2485 0 : }
2486 0 : }
2487 : }
2488 : //remove the temporary file
2489 0 : SWUnoHelper::UCB_DeleteFile( sTempURL );
2490 : }
2491 0 : SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE_END, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END), rSh.GetView().GetViewFrame()->GetObjectShell()));
2492 :
2493 : // reset the cursor inside
2494 0 : xResSet = NULL;
2495 0 : aDescriptor[daCursor] <<= xResSet;
2496 : }
2497 0 : if(pFound)
2498 : {
2499 0 : for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.size(); nPos++)
2500 : {
2501 0 : SwDSParam* pParam = &aDataSourceParams[nPos];
2502 0 : if(pParam == pFound)
2503 : {
2504 : try
2505 : {
2506 0 : uno::Reference<XComponent> xComp(pParam->xConnection, UNO_QUERY);
2507 0 : if(xComp.is())
2508 0 : xComp->dispose();
2509 : }
2510 0 : catch(const RuntimeException&)
2511 : {
2512 : //may be disposed already since multiple entries may have used the same connection
2513 : }
2514 0 : break;
2515 : }
2516 : //pFound doesn't need to be removed/deleted -
2517 : //this has been done by the SwConnectionDisposedListener_Impl already
2518 : }
2519 : }
2520 0 : DELETEZ(pImpl->pMergeDialog);
2521 : }
2522 :
2523 0 : void SwNewDBMgr::InsertText(SwWrtShell& rSh,
2524 : const Sequence< PropertyValue>& rProperties)
2525 : {
2526 0 : rtl::OUString sDataSource, sDataTableOrQuery;
2527 0 : uno::Reference<XResultSet> xResSet;
2528 0 : Sequence<Any> aSelection;
2529 0 : sal_Int16 nCmdType = CommandType::TABLE;
2530 0 : const PropertyValue* pValues = rProperties.getConstArray();
2531 0 : uno::Reference< XConnection> xConnection;
2532 0 : for(sal_Int32 nPos = 0; nPos < rProperties.getLength(); nPos++)
2533 : {
2534 0 : if ( pValues[nPos].Name == cDataSourceName )
2535 0 : pValues[nPos].Value >>= sDataSource;
2536 0 : else if ( pValues[nPos].Name == cCommand )
2537 0 : pValues[nPos].Value >>= sDataTableOrQuery;
2538 0 : else if ( pValues[nPos].Name == cCursor )
2539 0 : pValues[nPos].Value >>= xResSet;
2540 0 : else if ( pValues[nPos].Name == cSelection )
2541 0 : pValues[nPos].Value >>= aSelection;
2542 0 : else if ( pValues[nPos].Name == cCommandType )
2543 0 : pValues[nPos].Value >>= nCmdType;
2544 0 : else if ( pValues[nPos].Name == cActiveConnection )
2545 0 : pValues[nPos].Value >>= xConnection;
2546 : }
2547 0 : if(sDataSource.isEmpty() || sDataTableOrQuery.isEmpty() || !xResSet.is())
2548 : {
2549 : OSL_FAIL("PropertyValues missing or unset");
2550 0 : return;
2551 : }
2552 0 : Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
2553 0 : uno::Reference<XDataSource> xSource;
2554 0 : uno::Reference<XChild> xChild(xConnection, UNO_QUERY);
2555 0 : if(xChild.is())
2556 0 : xSource = uno::Reference<XDataSource>(xChild->getParent(), UNO_QUERY);
2557 0 : if(!xSource.is())
2558 0 : xSource = SwNewDBMgr::GetDbtoolsClient().getDataSource(sDataSource, xContext);
2559 0 : uno::Reference< XColumnsSupplier > xColSupp( xResSet, UNO_QUERY );
2560 0 : SwDBData aDBData;
2561 0 : aDBData.sDataSource = sDataSource;
2562 0 : aDBData.sCommand = sDataTableOrQuery;
2563 0 : aDBData.nCommandType = nCmdType;
2564 :
2565 0 : SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2566 : OSL_ENSURE(pFact, "SwAbstractDialogFactory fail!");
2567 :
2568 0 : AbstractSwInsertDBColAutoPilot* pDlg = pFact->CreateSwInsertDBColAutoPilot( rSh.GetView(),
2569 : xSource,
2570 : xColSupp,
2571 : aDBData,
2572 0 : DLG_AP_INSERT_DB_SEL );
2573 : OSL_ENSURE(pDlg, "Dialogdiet fail!");
2574 0 : if( RET_OK == pDlg->Execute() )
2575 : {
2576 0 : rtl::OUString sDummy;
2577 0 : if(!xConnection.is())
2578 0 : xConnection = xSource->getConnection(sDummy, sDummy);
2579 : try
2580 : {
2581 0 : pDlg->DataToDoc( aSelection , xSource, xConnection, xResSet);
2582 : }
2583 0 : catch(const Exception&)
2584 : {
2585 : OSL_FAIL("exception caught");
2586 0 : }
2587 : }
2588 0 : delete pDlg;
2589 :
2590 : }
2591 :
2592 : SwDbtoolsClient* SwNewDBMgr::pDbtoolsClient = NULL;
2593 :
2594 0 : SwDbtoolsClient& SwNewDBMgr::GetDbtoolsClient()
2595 : {
2596 0 : if ( !pDbtoolsClient )
2597 0 : pDbtoolsClient = new SwDbtoolsClient;
2598 0 : return *pDbtoolsClient;
2599 : }
2600 :
2601 10 : void SwNewDBMgr::RemoveDbtoolsClient()
2602 : {
2603 10 : delete pDbtoolsClient;
2604 10 : pDbtoolsClient = 0;
2605 10 : }
2606 :
2607 0 : uno::Reference<XDataSource> SwNewDBMgr::getDataSourceAsParent(const uno::Reference< XConnection>& _xConnection,const ::rtl::OUString& _sDataSourceName)
2608 : {
2609 0 : uno::Reference<XDataSource> xSource;
2610 : try
2611 : {
2612 0 : uno::Reference<XChild> xChild(_xConnection, UNO_QUERY);
2613 0 : if ( xChild.is() )
2614 0 : xSource = uno::Reference<XDataSource>(xChild->getParent(), UNO_QUERY);
2615 0 : if ( !xSource.is() )
2616 0 : xSource = SwNewDBMgr::GetDbtoolsClient().getDataSource(_sDataSourceName, ::comphelper::getProcessComponentContext());
2617 : }
2618 0 : catch(const Exception&)
2619 : {
2620 : OSL_FAIL("exception in getDataSourceAsParent caught");
2621 : }
2622 0 : return xSource;
2623 : }
2624 :
2625 0 : uno::Reference<XResultSet> SwNewDBMgr::createCursor(const ::rtl::OUString& _sDataSourceName,
2626 : const ::rtl::OUString& _sCommand,
2627 : sal_Int32 _nCommandType,
2628 : const uno::Reference<XConnection>& _xConnection
2629 : )
2630 : {
2631 0 : uno::Reference<XResultSet> xResultSet;
2632 : try
2633 : {
2634 0 : uno::Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
2635 0 : if( xMgr.is() )
2636 : {
2637 0 : uno::Reference<XInterface> xInstance = xMgr->createInstance("com.sun.star.sdb.RowSet");
2638 0 : uno::Reference<XPropertySet> xRowSetPropSet(xInstance, UNO_QUERY);
2639 0 : if(xRowSetPropSet.is())
2640 : {
2641 0 : xRowSetPropSet->setPropertyValue("DataSourceName", makeAny(_sDataSourceName));
2642 0 : xRowSetPropSet->setPropertyValue("ActiveConnection", makeAny(_xConnection));
2643 0 : xRowSetPropSet->setPropertyValue("Command", makeAny(_sCommand));
2644 0 : xRowSetPropSet->setPropertyValue("CommandType", makeAny(_nCommandType));
2645 :
2646 0 : uno::Reference< XCompletedExecution > xRowSet(xInstance, UNO_QUERY);
2647 :
2648 0 : if ( xRowSet.is() )
2649 : {
2650 0 : uno::Reference< XInteractionHandler > xHandler( InteractionHandler::createWithParent(comphelper::getComponentContext(xMgr), 0), UNO_QUERY_THROW );
2651 0 : xRowSet->executeWithCompletion(xHandler);
2652 : }
2653 0 : xResultSet = uno::Reference<XResultSet>(xRowSet, UNO_QUERY);
2654 0 : }
2655 0 : }
2656 : }
2657 0 : catch(const Exception&)
2658 : {
2659 : OSL_FAIL("Caught exception while creating a new RowSet!");
2660 : }
2661 0 : return xResultSet;
2662 : }
2663 :
2664 :
2665 : // merge all data into one resulting document and return the number of merged documents
2666 0 : sal_Int32 SwNewDBMgr::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
2667 : SwView& rSourceView )
2668 : {
2669 : // check the availability of all data in the config item
2670 0 : uno::Reference< XResultSet> xResultSet = rMMConfig.GetResultSet();
2671 0 : if(!xResultSet.is())
2672 0 : return false;
2673 0 : bInMerge = sal_True;
2674 0 : sal_Int32 nRet = 0;
2675 : pImpl->pMergeData = new SwDSParam(
2676 0 : rMMConfig.GetCurrentDBData(), xResultSet, rMMConfig.GetSelection());
2677 :
2678 : try{
2679 : //set to start position
2680 0 : if(pImpl->pMergeData->aSelection.getLength())
2681 : {
2682 0 : sal_Int32 nPos = 0;
2683 0 : pImpl->pMergeData->aSelection.getConstArray()[ pImpl->pMergeData->nSelectionIndex++ ] >>= nPos;
2684 0 : pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->absolute( nPos );
2685 0 : pImpl->pMergeData->CheckEndOfDB();
2686 0 : if(pImpl->pMergeData->nSelectionIndex >= pImpl->pMergeData->aSelection.getLength())
2687 0 : pImpl->pMergeData->bEndOfDB = sal_True;
2688 : }
2689 : else
2690 : {
2691 0 : pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->first();
2692 0 : pImpl->pMergeData->CheckEndOfDB();
2693 : }
2694 : }
2695 0 : catch(const Exception&)
2696 : {
2697 0 : pImpl->pMergeData->bEndOfDB = sal_True;
2698 0 : pImpl->pMergeData->CheckEndOfDB();
2699 : OSL_FAIL("exception in MergeNew()");
2700 : }
2701 :
2702 : //bCancel is set from the PrintMonitor
2703 0 : bCancel = sal_False;
2704 :
2705 0 : CreateMonitor aMonitorDlg(&rSourceView.GetEditWin());
2706 0 : aMonitorDlg.SetCancelHdl(LINK(this, SwNewDBMgr, PrtCancelHdl));
2707 0 : if (!IsMergeSilent())
2708 : {
2709 0 : aMonitorDlg.Show();
2710 0 : aMonitorDlg.Invalidate();
2711 0 : aMonitorDlg.Update();
2712 : // the print monitor needs some time to act
2713 0 : for( sal_uInt16 i = 0; i < 25; i++)
2714 0 : Application::Reschedule();
2715 : }
2716 :
2717 0 : SwWrtShell& rSourceShell = rSourceView.GetWrtShell();
2718 0 : sal_Bool bSynchronizedDoc = rSourceShell.IsLabelDoc() && rSourceShell.GetSectionFmtCount() > 1;
2719 : //save the settings of the first
2720 0 : rSourceShell.SttEndDoc(sal_True);
2721 0 : sal_uInt16 nStartingPageNo = rSourceShell.GetVirtPageNum();
2722 0 : String sModifiedStartingPageDesc;
2723 : String sStartingPageDesc = sModifiedStartingPageDesc = rSourceShell.GetPageDesc(
2724 0 : rSourceShell.GetCurPageDesc()).GetName();
2725 :
2726 : try
2727 : {
2728 : // create a target docshell to put the merged document into
2729 0 : SfxObjectShellRef xTargetDocShell( new SwDocShell( SFX_CREATE_MODE_STANDARD ) );
2730 0 : xTargetDocShell->DoInitNew( 0 );
2731 0 : SfxViewFrame* pTargetFrame = SfxViewFrame::LoadHiddenDocument( *xTargetDocShell, 0 );
2732 :
2733 : //the created window has to be located at the same position as the source window
2734 0 : Window& rTargetWindow = pTargetFrame->GetFrame().GetWindow();
2735 0 : Window& rSourceWindow = rSourceView.GetViewFrame()->GetFrame().GetWindow();
2736 0 : rTargetWindow.SetPosPixel(rSourceWindow.GetPosPixel());
2737 :
2738 0 : SwView* pTargetView = static_cast<SwView*>( pTargetFrame->GetViewShell() );
2739 0 : rMMConfig.SetTargetView(pTargetView);
2740 : //initiate SelectShell() to create sub shells
2741 0 : pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() );
2742 0 : SwWrtShell* pTargetShell = pTargetView->GetWrtShellPtr();
2743 : // #i63806#
2744 0 : const SwPageDesc* pSourcePageDesc = rSourceShell.FindPageDescByName( sStartingPageDesc );
2745 0 : const SwFrmFmt& rMaster = pSourcePageDesc->GetMaster();
2746 0 : bool bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive() ||
2747 0 : rMaster.GetFooter().IsActive();
2748 :
2749 :
2750 : // copy compatibility options
2751 0 : lcl_CopyCompatibilityOptions( rSourceShell, *pTargetShell);
2752 : // #72821# copy dynamic defaults
2753 0 : lcl_CopyDynamicDefaults( *rSourceShell.GetDoc(), *pTargetShell->GetDoc() );
2754 :
2755 :
2756 : long nStartRow, nEndRow;
2757 0 : sal_uLong nDocNo = 1;
2758 0 : sal_Int32 nDocCount = 0;
2759 0 : if( !IsMergeSilent() && lcl_getCountFromResultSet( nDocCount, pImpl->pMergeData->xResultSet ) )
2760 0 : aMonitorDlg.SetTotalCount( nDocCount );
2761 :
2762 0 : do
2763 : {
2764 0 : nStartRow = pImpl->pMergeData->xResultSet->getRow();
2765 0 : if (!IsMergeSilent())
2766 : {
2767 0 : aMonitorDlg.SetCurrentPosition( nDocNo );
2768 0 : aMonitorDlg.Invalidate();
2769 0 : aMonitorDlg.Update();
2770 : // the print monitor needs some time to act
2771 0 : for( sal_uInt16 i = 0; i < 25; i++)
2772 0 : Application::Reschedule();
2773 : }
2774 :
2775 : // copy the source document
2776 : // the copy will be closed later, but it is more safe to use SfxObjectShellLock here
2777 0 : SfxObjectShellLock xWorkDocSh;
2778 0 : if(nDocNo == 1 )
2779 : {
2780 0 : uno::Reference< util::XCloneable > xClone( rSourceView.GetDocShell()->GetModel(), uno::UNO_QUERY);
2781 0 : uno::Reference< lang::XUnoTunnel > xWorkDocShell( xClone->createClone(), uno::UNO_QUERY);
2782 0 : SwXTextDocument* pWorkModel = reinterpret_cast<SwXTextDocument*>(xWorkDocShell->getSomething(SwXTextDocument::getUnoTunnelId()));
2783 0 : xWorkDocSh = pWorkModel->GetDocShell();
2784 : }
2785 : else
2786 : {
2787 0 : xWorkDocSh = rSourceView.GetDocShell()->GetDoc()->CreateCopy(true);
2788 : }
2789 : //create a ViewFrame
2790 0 : SwView* pWorkView = static_cast< SwView* >( SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 )->GetViewShell() );
2791 0 : SwWrtShell& rWorkShell = pWorkView->GetWrtShell();
2792 0 : pWorkView->AttrChangedNotify( &rWorkShell );// in order for SelectShell to be called
2793 :
2794 : // merge the data
2795 0 : SwDoc* pWorkDoc = rWorkShell.GetDoc();
2796 0 : SwNewDBMgr* pWorkDBMgr = pWorkDoc->GetNewDBMgr();
2797 0 : pWorkDoc->SetNewDBMgr( this );
2798 0 : pWorkDoc->EmbedAllLinks();
2799 0 : SwUndoId nLastUndoId(UNDO_EMPTY);
2800 0 : if (rWorkShell.GetLastUndoInfo(0, & nLastUndoId))
2801 : {
2802 0 : if (UNDO_UI_DELETE_INVISIBLECNTNT == nLastUndoId)
2803 : {
2804 0 : rWorkShell.Undo();
2805 : }
2806 : }
2807 : // #i69485# lock fields to prevent access to the result set while calculating layout
2808 0 : rWorkShell.LockExpFlds();
2809 : // create a layout
2810 0 : rWorkShell.CalcLayout();
2811 0 : rWorkShell.UnlockExpFlds();
2812 0 : SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), rWorkShell.GetView().GetViewFrame()->GetObjectShell()));
2813 0 : rWorkShell.ViewShell::UpdateFlds();
2814 0 : SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), rWorkShell.GetView().GetViewFrame()->GetObjectShell()));
2815 :
2816 : // strip invisible content and convert fields to text
2817 0 : rWorkShell.RemoveInvisibleContent();
2818 0 : rWorkShell.ConvertFieldsToText();
2819 0 : rWorkShell.SetNumberingRestart();
2820 0 : if( bSynchronizedDoc )
2821 : {
2822 0 : lcl_RemoveSectionLinks( rWorkShell );
2823 : }
2824 :
2825 : // insert the document into the target document
2826 0 : rWorkShell.SttEndDoc(sal_False);
2827 0 : rWorkShell.SttEndDoc(sal_True);
2828 0 : rWorkShell.SelAll();
2829 0 : pTargetShell->SttEndDoc(sal_False);
2830 :
2831 : //#i63806# put the styles to the target document
2832 : //if the source uses headers or footers each new copy need to copy a new page styles
2833 0 : if(bPageStylesWithHeaderFooter)
2834 : {
2835 : //create a new pagestyle
2836 : //copy the pagedesc from the current document to the new document and change the name of the to-be-applied style
2837 :
2838 0 : SwDoc* pTargetDoc = pTargetShell->GetDoc();
2839 0 : String sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo );
2840 0 : pTargetShell->GetDoc()->MakePageDesc( sNewPageDescName );
2841 0 : SwPageDesc* pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
2842 0 : const SwPageDesc* pWorkPageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
2843 :
2844 0 : if(pWorkPageDesc && pTargetPageDesc)
2845 : {
2846 0 : pTargetDoc->CopyPageDesc( *pWorkPageDesc, *pTargetPageDesc, false );
2847 0 : sModifiedStartingPageDesc = sNewPageDescName;
2848 0 : lcl_CopyFollowPageDesc( *pTargetShell, *pWorkPageDesc, *pTargetPageDesc, nDocNo );
2849 0 : }
2850 : }
2851 0 : if(nDocNo == 1 || bPageStylesWithHeaderFooter)
2852 : {
2853 0 : pTargetView->GetDocShell()->_LoadStyles( *rSourceView.GetDocShell(), sal_True );
2854 : }
2855 0 : if(nDocNo > 1)
2856 : {
2857 0 : pTargetShell->InsertPageBreak( &sModifiedStartingPageDesc, nStartingPageNo );
2858 : }
2859 : else
2860 : {
2861 0 : pTargetShell->SetPageStyle(sModifiedStartingPageDesc);
2862 : }
2863 0 : sal_uInt16 nPageCountBefore = pTargetShell->GetPageCnt();
2864 : OSL_ENSURE(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended");
2865 : //#i51359# add a second paragraph in case there's only one
2866 : {
2867 0 : SwNodeIndex aIdx( pWorkDoc->GetNodes().GetEndOfExtras(), 2 );
2868 0 : SwPosition aTestPos( aIdx );
2869 0 : SwCursor aTestCrsr(aTestPos,0,false);
2870 0 : if(!aTestCrsr.MovePara(fnParaNext, fnParaStart))
2871 : {
2872 : //append a paragraph
2873 0 : pWorkDoc->AppendTxtNode( aTestPos );
2874 0 : }
2875 : }
2876 0 : pTargetShell->Paste( rWorkShell.GetDoc(), sal_True );
2877 : //convert fields in page styles (header/footer - has to be done after the first document has been pasted
2878 0 : if(1 == nDocNo)
2879 : {
2880 0 : pTargetShell->CalcLayout();
2881 0 : pTargetShell->ConvertFieldsToText();
2882 : }
2883 : //add the document info to the config item
2884 : SwDocMergeInfo aMergeInfo;
2885 0 : aMergeInfo.nStartPageInTarget = nPageCountBefore;
2886 : //#i72820# calculate layout to be able to find the correct page index
2887 0 : pTargetShell->CalcLayout();
2888 0 : aMergeInfo.nEndPageInTarget = pTargetShell->GetPageCnt();
2889 0 : aMergeInfo.nDBRow = nStartRow;
2890 0 : rMMConfig.AddMergedDocument( aMergeInfo );
2891 0 : ++nRet;
2892 :
2893 : // the print monitor needs some time to act
2894 0 : for( sal_uInt16 i = 0; i < 25; i++)
2895 0 : Application::Reschedule();
2896 :
2897 : //restore the ole DBMgr
2898 0 : pWorkDoc->SetNewDBMgr( pWorkDBMgr );
2899 : //now the temporary document should be closed
2900 0 : SfxObjectShellRef xDocSh(pWorkView->GetDocShell());
2901 0 : xDocSh->DoClose();
2902 0 : nEndRow = pImpl->pMergeData->xResultSet->getRow();
2903 0 : ++nDocNo;
2904 0 : } while( !bCancel &&
2905 0 : (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord()));
2906 :
2907 : //deselect all, go out of the frame and go to the beginning of the document
2908 0 : Point aPt(LONG_MIN, LONG_MIN);
2909 0 : pTargetShell->SelectObj(aPt, SW_LEAVE_FRAME);
2910 0 : if (pTargetShell->IsSelFrmMode())
2911 : {
2912 0 : pTargetShell->UnSelectFrm();
2913 0 : pTargetShell->LeaveSelFrmMode();
2914 : }
2915 0 : pTargetShell->EnterStdMode();
2916 0 : pTargetShell->SttDoc();
2917 :
2918 : }
2919 0 : catch(const Exception&)
2920 : {
2921 : OSL_FAIL("exception caught in SwNewDBMgr::MergeDocuments");
2922 : }
2923 0 : DELETEZ(pImpl->pMergeData);
2924 0 : bInMerge = sal_False;
2925 0 : return nRet;
2926 : }
2927 :
2928 276 : SwConnectionDisposedListener_Impl::SwConnectionDisposedListener_Impl(SwNewDBMgr& rMgr) :
2929 276 : rDBMgr(rMgr)
2930 : {
2931 276 : };
2932 :
2933 204 : SwConnectionDisposedListener_Impl::~SwConnectionDisposedListener_Impl()
2934 : {
2935 204 : };
2936 :
2937 0 : void SwConnectionDisposedListener_Impl::disposing( const EventObject& rSource )
2938 : throw (RuntimeException)
2939 : {
2940 0 : ::SolarMutexGuard aGuard;
2941 0 : uno::Reference<XConnection> xSource(rSource.Source, UNO_QUERY);
2942 0 : for(sal_uInt16 nPos = rDBMgr.aDataSourceParams.size(); nPos; nPos--)
2943 : {
2944 0 : SwDSParam* pParam = &rDBMgr.aDataSourceParams[nPos - 1];
2945 0 : if(pParam->xConnection.is() &&
2946 0 : (xSource == pParam->xConnection))
2947 : {
2948 0 : rDBMgr.aDataSourceParams.erase(rDBMgr.aDataSourceParams.begin() + nPos - 1);
2949 : }
2950 0 : }
2951 30 : }
2952 :
2953 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|