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