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