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