/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sw.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _SVSTDARR_STRINGSDTOR #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::osl; using namespace ::svx; using namespace ::com::sun::star; using namespace ::com::sun::star::text; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::container; using namespace ::com::sun::star::frame; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::sdb; using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::sdbcx; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::util; using namespace ::com::sun::star::task; using namespace ::com::sun::star::ui::dialogs; #define DB_SEP_SPACE 0 #define DB_SEP_TAB 1 #define DB_SEP_RETURN 2 #define DB_SEP_NEWLINE 3 SV_IMPL_PTRARR(SwDSParamArr, SwDSParamPtr); const sal_Char cCursor[] = "Cursor"; const sal_Char cCommand[] = "Command"; const sal_Char cCommandType[] = "CommandType"; const sal_Char cDataSourceName[] = "DataSourceName"; const sal_Char cSelection[] = "Selection"; const sal_Char cActiveConnection[] = "ActiveConnection"; // ----------------------------------------------------------------------------- // Use nameless namespace to avoid to rubbish the global namespace // ----------------------------------------------------------------------------- namespace { bool lcl_getCountFromResultSet( sal_Int32& rCount, const uno::Reference& xResultSet ) { uno::Reference xPrSet(xResultSet, UNO_QUERY); if(xPrSet.is()) { try { sal_Bool bFinal = sal_False; Any aFinal = xPrSet->getPropertyValue(C2U("IsRowCountFinal")); aFinal >>= bFinal; if(!bFinal) { xResultSet->last(); xResultSet->first(); } Any aCount = xPrSet->getPropertyValue(C2U("RowCount")); if( aCount >>= rCount ) return true; } catch(Exception&) { } } return false; } // #122799# copy compatibility options void lcl_CopyCompatibilityOptions( SwWrtShell& rSourceShell, SwWrtShell& rTargetShell) { IDocumentSettingAccess* pIDsa = rSourceShell.getIDocumentSettingAccess(); rTargetShell.SetParaSpaceMax( pIDsa->get(IDocumentSettingAccess::PARA_SPACE_MAX)); rTargetShell.SetParaSpaceMaxAtPages(pIDsa->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES)); rTargetShell.SetTabCompat( pIDsa->get(IDocumentSettingAccess::TAB_COMPAT)); rTargetShell.SetAddExtLeading( pIDsa->get(IDocumentSettingAccess::ADD_EXT_LEADING)); rTargetShell.SetUseVirDev( pIDsa->get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE)); rTargetShell.SetAddParaSpacingToTableCells( pIDsa->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS)); rTargetShell.SetUseFormerLineSpacing( pIDsa->get(IDocumentSettingAccess::OLD_LINE_SPACING)); rTargetShell.SetUseFormerObjectPositioning( pIDsa->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS)); rTargetShell.SetConsiderWrapOnObjPos( pIDsa->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION)); rTargetShell.SetUseFormerTextWrapping( pIDsa->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING)); } } /* -----------------09.12.2002 12:35----------------- * * --------------------------------------------------*/ class SwConnectionDisposedListener_Impl : public cppu::WeakImplHelper1 < lang::XEventListener > { SwNewDBMgr& rDBMgr; virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException); public: SwConnectionDisposedListener_Impl(SwNewDBMgr& rMgr); ~SwConnectionDisposedListener_Impl(); }; // ----------------------------------------------------------------------------- struct SwNewDBMgr_Impl { SwDSParam* pMergeData; AbstractMailMergeDlg* pMergeDialog; uno::Reference xDisposeListener; SwNewDBMgr_Impl(SwNewDBMgr& rDBMgr) :pMergeData(0) ,pMergeDialog(0) ,xDisposeListener(new SwConnectionDisposedListener_Impl(rDBMgr)) {} }; /*-- 24.10.2003 15:54:18--------------------------------------------------- -----------------------------------------------------------------------*/ void lcl_InitNumberFormatter(SwDSParam& rParam, uno::Reference xSource) { uno::Reference xMgr = ::comphelper::getProcessServiceFactory(); if( xMgr.is() ) { uno::Reference xInstance = xMgr->createInstance( C2U( "com.sun.star.util.NumberFormatter" )); rParam.xFormatter = uno::Reference(xInstance, UNO_QUERY) ; } if(!xSource.is()) xSource = SwNewDBMgr::getDataSourceAsParent(rParam.xConnection, rParam.sDataSource); uno::Reference xSourceProps(xSource, UNO_QUERY); if(xSourceProps.is()) { Any aFormats = xSourceProps->getPropertyValue(C2U("NumberFormatsSupplier")); if(aFormats.hasValue()) { uno::Reference xSuppl; aFormats >>= xSuppl; if(xSuppl.is()) { uno::Reference< XPropertySet > xSettings = xSuppl->getNumberFormatSettings(); Any aNull = xSettings->getPropertyValue(C2U("NullDate")); aNull >>= rParam.aNullDate; if(rParam.xFormatter.is()) rParam.xFormatter->attachNumberFormatsSupplier(xSuppl); } } } } /* -----------------------------17.07.00 17:04-------------------------------- ---------------------------------------------------------------------------*/ sal_Bool lcl_MoveAbsolute(SwDSParam* pParam, long nAbsPos) { sal_Bool bRet = sal_False; try { if(pParam->bScrollable) { bRet = pParam->xResultSet->absolute( nAbsPos ); } else { DBG_ERROR("no absolute positioning available"); } } catch(Exception aExcept) { } return bRet; } /* -----------------------------17.07.00 17:23-------------------------------- ---------------------------------------------------------------------------*/ sal_Bool lcl_GetColumnCnt(SwDSParam* pParam, const String& rColumnName, long nLanguage, String& rResult, double* pNumber) { uno::Reference< XColumnsSupplier > xColsSupp( pParam->xResultSet, UNO_QUERY ); uno::Reference xCols; try { xCols = xColsSupp->getColumns(); } catch( lang::DisposedException& ) { } if(!xCols.is() || !xCols->hasByName(rColumnName)) return sal_False; Any aCol = xCols->getByName(rColumnName); uno::Reference< XPropertySet > xColumnProps; aCol >>= xColumnProps; SwDBFormatData aFormatData; if(!pParam->xFormatter.is()) { uno::Reference xSource = SwNewDBMgr::getDataSourceAsParent( pParam->xConnection,pParam->sDataSource); lcl_InitNumberFormatter(*pParam, xSource ); } aFormatData.aNullDate = pParam->aNullDate; aFormatData.xFormatter = pParam->xFormatter; MsLangId::convertLanguageToLocale( (LanguageType)nLanguage, aFormatData.aLocale ); rResult = SwNewDBMgr::GetDBField( xColumnProps, aFormatData, pNumber); return sal_True; }; /*-------------------------------------------------------------------- Beschreibung: Daten importieren --------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::MergeNew(const SwMergeDescriptor& rMergeDesc ) { SetMergeType( rMergeDesc.nMergeType ); DBG_ASSERT(!bInMerge && !pImpl->pMergeData, "merge already activated!"); SwDBData aData; aData.nCommandType = CommandType::TABLE; uno::Reference xResSet; Sequence aSelection; uno::Reference< XConnection> xConnection; aData.sDataSource = rMergeDesc.rDescriptor.getDataSource(); rMergeDesc.rDescriptor[daCommand] >>= aData.sCommand; rMergeDesc.rDescriptor[daCommandType] >>= aData.nCommandType; if ( rMergeDesc.rDescriptor.has(daCursor) ) rMergeDesc.rDescriptor[daCursor] >>= xResSet; if ( rMergeDesc.rDescriptor.has(daSelection) ) rMergeDesc.rDescriptor[daSelection] >>= aSelection; if ( rMergeDesc.rDescriptor.has(daConnection) ) rMergeDesc.rDescriptor[daConnection] >>= xConnection; if(!aData.sDataSource.getLength() || !aData.sCommand.getLength() || !xResSet.is()) { return sal_False; } pImpl->pMergeData = new SwDSParam(aData, xResSet, aSelection); SwDSParam* pTemp = FindDSData(aData, sal_False); if(pTemp) *pTemp = *pImpl->pMergeData; else { //#94779# calls from the calculator may have added a connection with an invalid commandtype //"real" data base connections added here have to re-use the already available //DSData and set the correct CommandType SwDBData aTempData(aData); aData.nCommandType = -1; pTemp = FindDSData(aData, sal_False); if(pTemp) *pTemp = *pImpl->pMergeData; else { SwDSParam* pInsert = new SwDSParam(*pImpl->pMergeData); aDataSourceParams.Insert(pInsert, aDataSourceParams.Count()); try { uno::Reference xComponent(pInsert->xConnection, UNO_QUERY); if(xComponent.is()) xComponent->addEventListener(pImpl->xDisposeListener); } catch(Exception&) { } } } if(!pImpl->pMergeData->xConnection.is()) pImpl->pMergeData->xConnection = xConnection; // add an XEventListener try{ //set to start position if(pImpl->pMergeData->aSelection.getLength()) { sal_Int32 nPos = 0; pImpl->pMergeData->aSelection.getConstArray()[ pImpl->pMergeData->nSelectionIndex++ ] >>= nPos; pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->absolute( nPos ); pImpl->pMergeData->CheckEndOfDB(); if(pImpl->pMergeData->nSelectionIndex >= pImpl->pMergeData->aSelection.getLength()) pImpl->pMergeData->bEndOfDB = sal_True; } else { pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->first(); pImpl->pMergeData->CheckEndOfDB(); } } catch(Exception&) { pImpl->pMergeData->bEndOfDB = sal_True; pImpl->pMergeData->CheckEndOfDB(); DBG_ERROR("exception in MergeNew()"); } uno::Reference xSource = SwNewDBMgr::getDataSourceAsParent(xConnection,aData.sDataSource); lcl_InitNumberFormatter(*pImpl->pMergeData, xSource); rMergeDesc.rSh.ChgDBData(aData); bInMerge = sal_True; if (IsInitDBFields()) { // Bei Datenbankfeldern ohne DB-Name DB-Name von Dok einsetzen SvStringsDtor aDBNames(1, 1); aDBNames.Insert( new String(), 0); SwDBData aInsertData = rMergeDesc.rSh.GetDBData(); String sDBName = aInsertData.sDataSource; sDBName += DB_DELIM; sDBName += (String)aInsertData.sCommand; sDBName += DB_DELIM; sDBName += String::CreateFromInt32(aInsertData.nCommandType); rMergeDesc.rSh.ChangeDBFields( aDBNames, sDBName); SetInitDBFields(sal_False); } sal_Bool bRet = sal_True; switch(rMergeDesc.nMergeType) { case DBMGR_MERGE: bRet = Merge(&rMergeDesc.rSh); // Mischen break; case DBMGR_MERGE_MAILMERGE: // printing merge from 'old' merge dialog or from UNO-component case DBMGR_MERGE_MAILING: case DBMGR_MERGE_MAILFILES: case DBMGR_MERGE_SINGLE_FILE: // save files and send them as e-Mail if required bRet = MergeMailFiles(&rMergeDesc.rSh, rMergeDesc); break; default: // Einfuegen der selektierten Eintraege // (war: InsertRecord) ImportFromConnection(&rMergeDesc.rSh); break; } EndMerge(); return bRet; } /*-------------------------------------------------------------------- Beschreibung: Daten importieren --------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::Merge(SwWrtShell* pSh) { pSh->StartAllAction(); pSh->ViewShell::UpdateFlds(sal_True); pSh->SetModified(); pSh->EndAllAction(); return sal_True; } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void SwNewDBMgr::ImportFromConnection( SwWrtShell* pSh ) { if(pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB) { { pSh->StartAllAction(); pSh->StartUndo(UNDO_EMPTY); sal_Bool bGroupUndo(pSh->DoesGroupUndo()); pSh->DoGroupUndo(sal_False); if( pSh->HasSelection() ) pSh->DelRight(); SwWait *pWait = 0; { sal_uLong i = 0; do { ImportDBEntry(pSh); if( 10 == ++i ) pWait = new SwWait( *pSh->GetView().GetDocShell(), true ); } while(ToNextMergeRecord()); } pSh->DoGroupUndo(bGroupUndo); pSh->EndUndo(UNDO_EMPTY); pSh->EndAllAction(); delete pWait; } } } /*-----------------24.02.97 10.30------------------- --------------------------------------------------*/ String lcl_FindColumn(const String& sFormatStr,sal_uInt16 &nUsedPos, sal_uInt8 &nSeparator) { String sReturn; sal_uInt16 nLen = sFormatStr.Len(); nSeparator = 0xff; while(nUsedPos < nLen && nSeparator == 0xff) { sal_Unicode cAkt = sFormatStr.GetChar(nUsedPos); switch(cAkt) { case ',': nSeparator = DB_SEP_SPACE; break; case ';': nSeparator = DB_SEP_RETURN; break; case ':': nSeparator = DB_SEP_TAB; break; case '#': nSeparator = DB_SEP_NEWLINE; break; default: sReturn += cAkt; } nUsedPos++; } return sReturn; } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ void SwNewDBMgr::ImportDBEntry(SwWrtShell* pSh) { if(pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB) { uno::Reference< XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, UNO_QUERY ); uno::Reference xCols = xColsSupp->getColumns(); String sFormatStr; sal_uInt16 nFmtLen = sFormatStr.Len(); if( nFmtLen ) { const char cSpace = ' '; const char cTab = '\t'; sal_uInt16 nUsedPos = 0; sal_uInt8 nSeparator; String sColumn = lcl_FindColumn(sFormatStr, nUsedPos, nSeparator); while( sColumn.Len() ) { if(!xCols->hasByName(sColumn)) return; Any aCol = xCols->getByName(sColumn); uno::Reference< XPropertySet > xColumnProp; aCol >>= xColumnProp; if(xColumnProp.is()) { SwDBFormatData aDBFormat; String sInsert = GetDBField( xColumnProp, aDBFormat); if( DB_SEP_SPACE == nSeparator ) sInsert += cSpace; else if( DB_SEP_TAB == nSeparator) sInsert += cTab; pSh->Insert(sInsert); if( DB_SEP_RETURN == nSeparator) pSh->SplitNode(); else if(DB_SEP_NEWLINE == nSeparator) pSh->InsertLineBreak(); } else { // Spalte nicht gefunden -> Fehler anzeigen String sInsert = '?'; sInsert += sColumn; sInsert += '?'; pSh->Insert(sInsert); } sColumn = lcl_FindColumn(sFormatStr, nUsedPos, nSeparator); } pSh->SplitNode(); } else { String sStr; Sequence aColNames = xCols->getElementNames(); const rtl::OUString* pColNames = aColNames.getConstArray(); long nLength = aColNames.getLength(); for(long i = 0; i < nLength; i++) { Any aCol = xCols->getByName(pColNames[i]); uno::Reference< XPropertySet > xColumnProp; aCol >>= xColumnProp; SwDBFormatData aDBFormat; sStr += GetDBField( xColumnProp, aDBFormat); if (i < nLength - 1) sStr += '\t'; } pSh->SwEditShell::Insert2(sStr); pSh->SwFEShell::SplitNode(); // Zeilenvorschub } } } /*-------------------------------------------------------------------- Beschreibung: Listbox mit Tabellenliste fuellen --------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::GetTableNames(ListBox* pListBox, const String& rDBName) { sal_Bool bRet = sal_False; String sOldTableName(pListBox->GetSelectEntry()); pListBox->Clear(); SwDSParam* pParam = FindDSConnection(rDBName, sal_False); uno::Reference< XConnection> xConnection; if(pParam && pParam->xConnection.is()) xConnection = pParam->xConnection; else { rtl::OUString sDBName(rDBName); if ( sDBName.getLength() ) xConnection = RegisterConnection( sDBName ); } if(xConnection.is()) { uno::Reference xTSupplier = uno::Reference(xConnection, UNO_QUERY); if(xTSupplier.is()) { uno::Reference xTbls = xTSupplier->getTables(); Sequence aTbls = xTbls->getElementNames(); const rtl::OUString* pTbls = aTbls.getConstArray(); for(long i = 0; i < aTbls.getLength(); i++) { sal_uInt16 nEntry = pListBox->InsertEntry(pTbls[i]); pListBox->SetEntryData(nEntry, (void*)0); } } uno::Reference xQSupplier = uno::Reference(xConnection, UNO_QUERY); if(xQSupplier.is()) { uno::Reference xQueries = xQSupplier->getQueries(); Sequence aQueries = xQueries->getElementNames(); const rtl::OUString* pQueries = aQueries.getConstArray(); for(long i = 0; i < aQueries.getLength(); i++) { sal_uInt16 nEntry = pListBox->InsertEntry(pQueries[i]); pListBox->SetEntryData(nEntry, (void*)1); } } if (sOldTableName.Len()) pListBox->SelectEntry(sOldTableName); bRet = sal_True; } return bRet; } /*-------------------------------------------------------------------- Beschreibung: Listbox mit Spaltennamen einer Datenbank fuellen --------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::GetColumnNames(ListBox* pListBox, const String& rDBName, const String& rTableName, sal_Bool bAppend) { if (!bAppend) pListBox->Clear(); SwDBData aData; aData.sDataSource = rDBName; aData.sCommand = rTableName; aData.nCommandType = -1; SwDSParam* pParam = FindDSData(aData, sal_False); uno::Reference< XConnection> xConnection; if(pParam && pParam->xConnection.is()) xConnection = pParam->xConnection; else { rtl::OUString sDBName(rDBName); xConnection = RegisterConnection( sDBName ); } uno::Reference< XColumnsSupplier> xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName); if(xColsSupp.is()) { uno::Reference xCols = xColsSupp->getColumns(); const Sequence aColNames = xCols->getElementNames(); const rtl::OUString* pColNames = aColNames.getConstArray(); for(int nCol = 0; nCol < aColNames.getLength(); nCol++) { pListBox->InsertEntry(pColNames[nCol]); } ::comphelper::disposeComponent( xColsSupp ); } return(sal_True); } /* -----------------------------08.06.01 15:11-------------------------------- ---------------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::GetColumnNames(ListBox* pListBox, uno::Reference< XConnection> xConnection, const String& rTableName, sal_Bool bAppend) { if (!bAppend) pListBox->Clear(); uno::Reference< XColumnsSupplier> xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName); if(xColsSupp.is()) { uno::Reference xCols = xColsSupp->getColumns(); const Sequence aColNames = xCols->getElementNames(); const rtl::OUString* pColNames = aColNames.getConstArray(); for(int nCol = 0; nCol < aColNames.getLength(); nCol++) { pListBox->InsertEntry(pColNames[nCol]); } ::comphelper::disposeComponent( xColsSupp ); } return(sal_True); } /*-------------------------------------------------------------------- Beschreibung: CTOR --------------------------------------------------------------------*/ SwNewDBMgr::SwNewDBMgr() : nMergeType(DBMGR_INSERT), bInitDBFields(sal_False), bInMerge(sal_False), bMergeSilent(sal_False), bMergeLock(sal_False), pImpl(new SwNewDBMgr_Impl(*this)), pMergeEvtSrc(NULL) { } /* -----------------------------18.07.00 08:56-------------------------------- ---------------------------------------------------------------------------*/ SwNewDBMgr::~SwNewDBMgr() { for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.Count(); nPos++) { SwDSParam* pParam = aDataSourceParams[nPos]; if(pParam->xConnection.is()) { try { uno::Reference xComp(pParam->xConnection, UNO_QUERY); if(xComp.is()) xComp->dispose(); } catch(const RuntimeException& ) { //may be disposed already since multiple entries may have used the same connection } } } delete pImpl; } /*-------------------------------------------------------------------- Beschreibung: Serienbriefe als einzelne Dokumente speichern --------------------------------------------------------------------*/ String lcl_FindUniqueName(SwWrtShell* pTargetShell, const String& rStartingPageDesc, sal_uLong nDocNo ) { do { String sTest = rStartingPageDesc; sTest += String::CreateFromInt32( nDocNo ); if( !pTargetShell->FindPageDescByName( sTest ) ) return sTest; ++nDocNo; }while(true); } void lcl_CopyDynamicDefaults( const SwDoc& rSource, SwDoc& rTarget ) { sal_uInt16 __FAR_DATA aRangeOfDefaults[] = { RES_FRMATR_BEGIN, RES_FRMATR_END-1, RES_CHRATR_BEGIN, RES_CHRATR_END-1, RES_PARATR_BEGIN, RES_PARATR_END-1, // --> OD 2008-02-25 #refactorlists## RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1, // <-- RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1, 0 }; SfxItemSet aNewDefaults( rTarget.GetAttrPool(), aRangeOfDefaults ); sal_uInt16 nWhich; sal_uInt16 nRange = 0; while( aRangeOfDefaults[nRange] != 0) { for( nWhich = aRangeOfDefaults[nRange]; nWhich < aRangeOfDefaults[nRange + 1]; ++nWhich ) { const SfxPoolItem& rSourceAttr = rSource.GetDefault( nWhich ); if( rSourceAttr != rTarget.GetDefault( nWhich ) ) aNewDefaults.Put( rSourceAttr ); } nRange += 2; } if( aNewDefaults.Count() ) rTarget.SetDefault( aNewDefaults ); } void lcl_CopyFollowPageDesc( SwWrtShell& rTargetShell, const SwPageDesc& rSourcePageDesc, const SwPageDesc& rTargetPageDesc, const sal_uLong nDocNo ) { //now copy the follow page desc, too const SwPageDesc* pFollowPageDesc = rSourcePageDesc.GetFollow(); String sFollowPageDesc = pFollowPageDesc->GetName(); if( sFollowPageDesc != rSourcePageDesc.GetName() ) { SwDoc* pTargetDoc = rTargetShell.GetDoc(); String sNewFollowPageDesc = lcl_FindUniqueName(&rTargetShell, sFollowPageDesc, nDocNo ); sal_uInt16 nNewDesc = pTargetDoc->MakePageDesc( sNewFollowPageDesc ); SwPageDesc& rTargetFollowPageDesc = pTargetDoc->_GetPageDesc( nNewDesc ); pTargetDoc->CopyPageDesc( *pFollowPageDesc, rTargetFollowPageDesc, sal_False ); SwPageDesc aDesc( rTargetPageDesc ); aDesc.SetFollow( &rTargetFollowPageDesc ); pTargetDoc->ChgPageDesc( rTargetPageDesc.GetName(), aDesc ); } } void lcl_RemoveSectionLinks( SwWrtShell& rWorkShell ) { //reset all links of the sections of synchronized labels sal_uInt16 nSections = rWorkShell.GetSectionFmtCount(); for( sal_uInt16 nSection = 0; nSection < nSections; ++nSection ) { SwSectionData aSectionData( *rWorkShell.GetSectionFmt( nSection ).GetSection() ); if( aSectionData.GetType() == FILE_LINK_SECTION ) { aSectionData.SetType( CONTENT_SECTION ); aSectionData.SetLinkFileName( String() ); rWorkShell.UpdateSection( nSection, aSectionData ); } } rWorkShell.SetLabelDoc( sal_False ); } sal_Bool SwNewDBMgr::MergeMailFiles(SwWrtShell* pSourceShell, const SwMergeDescriptor& rMergeDescriptor) { //check if the doc is synchronized and contains at least one linked section sal_Bool bSynchronizedDoc = pSourceShell->IsLabelDoc() && pSourceShell->GetSectionFmtCount() > 1; sal_Bool bLoop = sal_True; sal_Bool bEMail = rMergeDescriptor.nMergeType == DBMGR_MERGE_MAILING; const bool bAsSingleFile = rMergeDescriptor.nMergeType == DBMGR_MERGE_SINGLE_FILE; ::rtl::Reference< MailDispatcher > xMailDispatcher; ::rtl::OUString sBodyMimeType; rtl_TextEncoding eEncoding = ::gsl_getSystemTextEncoding(); if(bEMail) { xMailDispatcher.set( new MailDispatcher(rMergeDescriptor.xSmtpServer)); if(!rMergeDescriptor.bSendAsAttachment && rMergeDescriptor.bSendAsHTML) { sBodyMimeType = ::rtl::OUString::createFromAscii("text/html; charset="); sBodyMimeType += ::rtl::OUString::createFromAscii( rtl_getBestMimeCharsetFromTextEncoding( eEncoding )); SvxHtmlOptions* pHtmlOptions = SvxHtmlOptions::Get(); eEncoding = pHtmlOptions->GetTextEncoding(); } else sBodyMimeType = ::rtl::OUString::createFromAscii("text/plain; charset=UTF-8; format=flowed"); } uno::Reference< XPropertySet > xColumnProp; { sal_Bool bColumnName = sEMailAddrFld.Len() > 0; if (bColumnName) { uno::Reference< XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, UNO_QUERY ); uno::Reference xCols = xColsSupp->getColumns(); if(!xCols->hasByName(sEMailAddrFld)) return sal_False; Any aCol = xCols->getByName(sEMailAddrFld); aCol >>= xColumnProp; } SfxDispatcher* pSfxDispatcher = pSourceShell->GetView().GetViewFrame()->GetDispatcher(); SwDocShell* pSourrceDocSh = pSourceShell->GetView().GetDocShell(); pSfxDispatcher->Execute( pSourrceDocSh->HasName() ? SID_SAVEDOC : SID_SAVEASDOC, SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD); // has document been saved successfully? if( !pSourrceDocSh->IsModified() ) { SfxMedium* pOrig = pSourceShell->GetView().GetDocShell()->GetMedium(); String sSourceDocumentURL(pOrig->GetURLObject().GetMainURL( INetURLObject::NO_DECODE )); const SfxFilter* pSfxFlt = SwIoSystem::GetFileFilter( sSourceDocumentURL, ::aEmptyStr ); const SfxFilter* pStoreToFilter = pSfxFlt; SfxFilterContainer* pFilterContainer = SwDocShell::Factory().GetFilterContainer(); const String* pStoreToFilterOptions = 0; // if a save_to filter is set then use it - otherwise use the default if( bEMail && !rMergeDescriptor.bSendAsAttachment ) { String sExtension( String::CreateFromAscii( rMergeDescriptor.bSendAsHTML ? "html" : "txt" )); pStoreToFilter = pFilterContainer->GetFilter4Extension(sExtension, SFX_FILTER_EXPORT); } else if( rMergeDescriptor.sSaveToFilter.Len()) { const SfxFilter* pFilter = pFilterContainer->GetFilter4FilterName( rMergeDescriptor.sSaveToFilter ); if(pFilter) { pStoreToFilter = pFilter; if(rMergeDescriptor.sSaveToFilterOptions.Len()) pStoreToFilterOptions = &rMergeDescriptor.sSaveToFilterOptions; } } bCancel = sal_False; // in case of creating a single resulting file this has to be created here SwWrtShell* pTargetShell = 0; // the shell will be explicitly closed at the end of the method, but it is // still more safe to use SfxObjectShellLock here SfxObjectShellLock xTargetDocShell; SwView* pTargetView = 0; std::auto_ptr< utl::TempFile > aTempFile; String sModifiedStartingPageDesc; String sStartingPageDesc; sal_uInt16 nStartingPageNo = 0; bool bPageStylesWithHeaderFooter = false; if(bAsSingleFile || rMergeDescriptor.bCreateSingleFile) { // create a target docshell to put the merged document into xTargetDocShell = new SwDocShell( SFX_CREATE_MODE_STANDARD ); xTargetDocShell->DoInitNew( 0 ); SfxViewFrame* pTargetFrame = SfxViewFrame::LoadHiddenDocument( *xTargetDocShell, 0 ); pTargetView = static_cast( pTargetFrame->GetViewShell() ); //initiate SelectShell() to create sub shells pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() ); pTargetShell = pTargetView->GetWrtShellPtr(); //copy the styles from the source to the target document SwgReaderOption aOpt; aOpt.SetTxtFmts( sal_True ); aOpt.SetFrmFmts( sal_True ); aOpt.SetPageDescs( sal_True ); aOpt.SetNumRules( sal_True ); aOpt.SetMerge( sal_False ); pTargetView->GetDocShell()->LoadStylesFromFile( sSourceDocumentURL, aOpt, sal_True ); //determine the page style and number used at the start of the source document pSourceShell->SttEndDoc(sal_True); nStartingPageNo = pSourceShell->GetVirtPageNum(); sStartingPageDesc = sModifiedStartingPageDesc = pSourceShell->GetPageDesc( pSourceShell->GetCurPageDesc()).GetName(); // #122799# copy compatibility options lcl_CopyCompatibilityOptions( *pSourceShell, *pTargetShell); // #72821# copy dynamic defaults lcl_CopyDynamicDefaults( *pSourceShell->GetDoc(), *pTargetShell->GetDoc() ); // #i72517# const SwPageDesc* pSourcePageDesc = pSourceShell->FindPageDescByName( sStartingPageDesc ); const SwFrmFmt& rMaster = pSourcePageDesc->GetMaster(); bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive() || rMaster.GetFooter().IsActive(); } PrintMonitor aPrtMonDlg(&pSourceShell->GetView().GetEditWin(), PrintMonitor::MONITOR_TYPE_PRINT); aPrtMonDlg.aDocName.SetText(pSourceShell->GetView().GetDocShell()->GetTitle(22)); aPrtMonDlg.aCancel.SetClickHdl(LINK(this, SwNewDBMgr, PrtCancelHdl)); if (!IsMergeSilent()) aPrtMonDlg.Show(); // Progress, um KeyInputs zu unterbinden SfxProgress aProgress(pSourrceDocSh, ::aEmptyStr, 1); // Alle Dispatcher sperren SfxViewFrame* pViewFrm = SfxViewFrame::GetFirst(pSourrceDocSh); while (pViewFrm) { pViewFrm->GetDispatcher()->Lock(sal_True); pViewFrm = SfxViewFrame::GetNext(*pViewFrm, pSourrceDocSh); } sal_uLong nDocNo = 1; long nStartRow, nEndRow; // collect temporary files ::std::vector< String> aFilesToRemove; do { nStartRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0; { String sPath(sSubject); String sAddress; if( !bEMail && bColumnName ) { SwDBFormatData aDBFormat; aDBFormat.xFormatter = pImpl->pMergeData->xFormatter; aDBFormat.aNullDate = pImpl->pMergeData->aNullDate; sAddress = GetDBField( xColumnProp, aDBFormat); if (!sAddress.Len()) sAddress = '_'; sPath += sAddress; } // create a new temporary file name - only done once in case of bCreateSingleFile if( 1 == nDocNo || (!rMergeDescriptor.bCreateSingleFile && !bAsSingleFile) ) { INetURLObject aEntry(sPath); String sLeading; //#i97667# if the name is from a database field then it will be used _as is_ if( sAddress.Len() ) sLeading = sAddress; else sLeading = aEntry.GetBase(); aEntry.removeSegment(); sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE ); String sExt( pStoreToFilter->GetDefaultExtension() ); sExt.EraseLeadingChars('*'); aTempFile = std::auto_ptr< utl::TempFile >( new utl::TempFile(sLeading,&sExt,&sPath )); if( bAsSingleFile ) aTempFile->EnableKillingFile(); } if( !aTempFile->IsValid() ) { ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED ); bLoop = sal_False; bCancel = sal_True; } else { INetURLObject aTempFileURL(aTempFile->GetURL()); aPrtMonDlg.aPrinter.SetText( aTempFileURL.GetBase() ); String sStat(SW_RES(STR_STATSTR_LETTER)); // Brief sStat += ' '; sStat += String::CreateFromInt32( nDocNo ); aPrtMonDlg.aPrintInfo.SetText(sStat); // Rechenzeit fuer Save-Monitor: for (sal_uInt16 i = 0; i < 10; i++) Application::Reschedule(); // Create and save new document // The SfxObjectShell will be closed explicitly later but it is more safe to use SfxObjectShellLock here SfxObjectShellLock xWorkDocSh( new SwDocShell( SFX_CREATE_MODE_INTERNAL )); SfxMedium* pWorkMed = new SfxMedium( sSourceDocumentURL, STREAM_STD_READ, sal_True ); pWorkMed->SetFilter( pSfxFlt ); if (xWorkDocSh->DoLoad(pWorkMed)) { //create a view frame for the document SfxViewFrame* pWorkFrame = SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 ); //request the layout calculation SwWrtShell& rWorkShell = static_cast< SwView* >(pWorkFrame->GetViewShell())->GetWrtShell(); rWorkShell.CalcLayout(); SwDoc* pWorkDoc = ((SwDocShell*)(&xWorkDocSh))->GetDoc(); SwNewDBMgr* pOldDBMgr = pWorkDoc->GetNewDBMgr(); pWorkDoc->SetNewDBMgr( this ); SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), xWorkDocSh)); pWorkDoc->UpdateFlds(NULL, false); SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), xWorkDocSh)); // alle versteckten Felder/Bereiche entfernen pWorkDoc->RemoveInvisibleContent(); // launch MailMergeEvent if required const SwXMailMerge *pEvtSrc = GetMailMergeEvtSrc(); if(pEvtSrc) { uno::Reference< XInterface > xRef( (XMailMergeBroadcaster *) pEvtSrc ); text::MailMergeEvent aEvt( xRef, xWorkDocSh->GetModel() ); pEvtSrc->LaunchMailMergeEvent( aEvt ); } if(rMergeDescriptor.bCreateSingleFile || bAsSingleFile ) { DBG_ASSERT( pTargetShell, "no target shell available!" ); // copy created file into the target document rWorkShell.ConvertFieldsToText(); rWorkShell.SetNumberingRestart(); if( bSynchronizedDoc ) { lcl_RemoveSectionLinks( rWorkShell ); } // insert the document into the target document rWorkShell.SttEndDoc(sal_False); rWorkShell.SttEndDoc(sal_True); rWorkShell.SelAll(); pTargetShell->SwCrsrShell::SttEndDoc( sal_False ); //#i72517# the headers and footers are still those from the source - update in case of fields inside header/footer if( !nDocNo && bPageStylesWithHeaderFooter ) pTargetShell->GetView().GetDocShell()->_LoadStyles( *rWorkShell.GetView().GetDocShell(), sal_True ); //#i72517# put the styles to the target document //if the source uses headers or footers each new copy need to copy a new page styles if(bPageStylesWithHeaderFooter) { //create a new pagestyle //copy the pagedesc from the current document to the new document and change the name of the to-be-applied style SwDoc* pTargetDoc = pTargetShell->GetDoc(); SwPageDesc* pSourcePageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc ); String sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo ); pTargetDoc->MakePageDesc( sNewPageDescName ); SwPageDesc* pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName ); if(pSourcePageDesc && pTargetPageDesc) { pTargetDoc->CopyPageDesc( *pSourcePageDesc, *pTargetPageDesc, sal_False ); sModifiedStartingPageDesc = sNewPageDescName; lcl_CopyFollowPageDesc( *pTargetShell, *pSourcePageDesc, *pTargetPageDesc, nDocNo ); } } if(nDocNo > 1) pTargetShell->InsertPageBreak( &sModifiedStartingPageDesc, nStartingPageNo ); else pTargetShell->SetPageStyle(sModifiedStartingPageDesc); DBG_ASSERT(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended"); //#i51359# add a second paragraph in case there's only one { SwNodeIndex aIdx( pWorkDoc->GetNodes().GetEndOfExtras(), 2 ); SwPosition aTestPos( aIdx ); SwCursor aTestCrsr(aTestPos,0,false); if(!aTestCrsr.MovePara(fnParaNext, fnParaStart)) { //append a paragraph pWorkDoc->AppendTxtNode( aTestPos ); } } pTargetShell->Paste( rWorkShell.GetDoc(), sal_True ); //convert fields in page styles (header/footer - has to be done after the first document has been pasted if(1 == nDocNo) { pTargetShell->CalcLayout(); pTargetShell->ConvertFieldsToText(); } } else { String sFileURL = aTempFileURL.GetMainURL( INetURLObject::NO_DECODE ); SfxMedium* pDstMed = new SfxMedium( sFileURL, STREAM_STD_READWRITE, sal_True ); pDstMed->SetFilter( pStoreToFilter ); if(pDstMed->GetItemSet()) { if(pStoreToFilterOptions ) pDstMed->GetItemSet()->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, *pStoreToFilterOptions)); if(rMergeDescriptor.aSaveToFilterData.getLength()) pDstMed->GetItemSet()->Put(SfxUsrAnyItem(SID_FILTER_DATA, makeAny(rMergeDescriptor.aSaveToFilterData))); } //convert fields to text if we are exporting to PDF //this prevents a second merge while updating the fields in SwXTextDocument::getRendererCount() if( pStoreToFilter && pStoreToFilter->GetFilterName().EqualsAscii("writer_pdf_Export")) rWorkShell.ConvertFieldsToText(); xWorkDocSh->DoSaveAs(*pDstMed); xWorkDocSh->DoSaveCompleted(pDstMed); if( xWorkDocSh->GetError() ) { // error message ?? ErrorHandler::HandleError( xWorkDocSh->GetError() ); bCancel = sal_True; bLoop = sal_False; } if( bEMail ) { SwDBFormatData aDBFormat; aDBFormat.xFormatter = pImpl->pMergeData->xFormatter; aDBFormat.aNullDate = pImpl->pMergeData->aNullDate; String sMailAddress = GetDBField( xColumnProp, aDBFormat); if(!SwMailMergeHelper::CheckMailAddress( sMailAddress )) { DBG_ERROR("invalid e-Mail address in database column"); } else { SwMailMessage* pMessage = 0; uno::Reference< mail::XMailMessage > xMessage = pMessage = new SwMailMessage; if(rMergeDescriptor.pMailMergeConfigItem->IsMailReplyTo()) pMessage->setReplyToAddress(rMergeDescriptor.pMailMergeConfigItem->GetMailReplyTo()); pMessage->addRecipient( sMailAddress ); pMessage->SetSenderAddress( rMergeDescriptor.pMailMergeConfigItem->GetMailAddress() ); ::rtl::OUString sBody; if(rMergeDescriptor.bSendAsAttachment) { sBody = rMergeDescriptor.sMailBody; mail::MailAttachment aAttach; aAttach.Data = new SwMailTransferable( sFileURL, rMergeDescriptor.sAttachmentName, pStoreToFilter->GetMimeType()); aAttach.ReadableName = rMergeDescriptor.sAttachmentName; pMessage->addAttachment( aAttach ); } else { { //read in the temporary file and use it as mail body SfxMedium aMedium( sFileURL, STREAM_READ, sal_True); SvStream* pInStream = aMedium.GetInStream(); DBG_ASSERT(pInStream, "no output file created?"); if(pInStream) { pInStream->SetStreamCharSet( eEncoding ); ByteString sLine; sal_Bool bDone = pInStream->ReadLine( sLine ); while ( bDone ) { sBody += String(sLine, eEncoding); sBody += ::rtl::OUString('\n'); bDone = pInStream->ReadLine( sLine ); } } } } pMessage->setSubject( rMergeDescriptor.sSubject ); uno::Reference< datatransfer::XTransferable> xBody = new SwMailTransferable( sBody, sBodyMimeType); pMessage->setBody( xBody ); if(rMergeDescriptor.aCopiesTo.getLength()) { const ::rtl::OUString* pCopies = rMergeDescriptor.aCopiesTo.getConstArray(); for( sal_Int32 nToken = 0; nToken < rMergeDescriptor.aCopiesTo.getLength(); ++nToken) pMessage->addCcRecipient( pCopies[nToken] ); } if(rMergeDescriptor.aBlindCopiesTo.getLength()) { const ::rtl::OUString* pCopies = rMergeDescriptor.aBlindCopiesTo.getConstArray(); for( sal_Int32 nToken = 0; nToken < rMergeDescriptor.aBlindCopiesTo.getLength(); ++nToken) pMessage->addBccRecipient( pCopies[nToken] ); } xMailDispatcher->enqueueMailMessage( xMessage ); if(!xMailDispatcher->isStarted()) xMailDispatcher->start(); //schedule for removal aFilesToRemove.push_back(sFileURL); } } } pWorkDoc->SetNewDBMgr( pOldDBMgr ); } xWorkDocSh->DoClose(); } } nDocNo++; nEndRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0; } while( !bCancel && (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord())); aPrtMonDlg.Show( sal_False ); // save the single output document if(rMergeDescriptor.bCreateSingleFile || bAsSingleFile) { if( rMergeDescriptor.nMergeType != DBMGR_MERGE_MAILMERGE ) { DBG_ASSERT( aTempFile.get(), "Temporary file not available" ); INetURLObject aTempFileURL(bAsSingleFile ? sSubject : aTempFile->GetURL()); SfxMedium* pDstMed = new SfxMedium( aTempFileURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_STD_READWRITE, sal_True ); pDstMed->SetFilter( pStoreToFilter ); if(pDstMed->GetItemSet()) { if(pStoreToFilterOptions ) pDstMed->GetItemSet()->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, *pStoreToFilterOptions)); if(rMergeDescriptor.aSaveToFilterData.getLength()) pDstMed->GetItemSet()->Put(SfxUsrAnyItem(SID_FILTER_DATA, makeAny(rMergeDescriptor.aSaveToFilterData))); } xTargetDocShell->DoSaveAs(*pDstMed); xTargetDocShell->DoSaveCompleted(pDstMed); if( xTargetDocShell->GetError() ) { // error message ?? ErrorHandler::HandleError( xTargetDocShell->GetError() ); bLoop = sal_False; } } else if( pTargetView ) // must be available! { //print the target document #if OSL_DEBUG_LEVEL > 1 sal_Bool _bVal; sal_Int16 _nVal; rtl::OUString _sVal; const beans::PropertyValue* pDbgPrintOptions = rMergeDescriptor.aPrintOptions.getConstArray(); for( sal_Int32 nOption = 0; nOption < rMergeDescriptor.aPrintOptions.getLength(); ++nOption) { rtl::OUString aName( pDbgPrintOptions[nOption].Name ); uno::Any aVal( pDbgPrintOptions[nOption].Value ); aVal >>= _bVal; aVal >>= _nVal; aVal >>= _sVal; } #endif // printing should be done synchronously otherwise the document // might already become invalid during the process uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions ); const sal_Int32 nOpts = aOptions.getLength(); aOptions.realloc( nOpts + 1 ); aOptions[ nOpts ].Name = rtl::OUString::createFromAscii( "Wait" ); aOptions[ nOpts ].Value <<= sal_True ; // aPrintArgs.Put(SfxBoolItem(FN_QRY_MERGE, sal_True) ); // // #i52629# aynchronous printing should only be done in silent mode - otherwise // // the printer dialog does not come up // aPrintArgs.Put( SfxBoolItem( SID_ASYNCHRON, rMergeDescriptor.bPrintAsync )); // move print options const beans::PropertyValue* pPrintOptions = rMergeDescriptor.aPrintOptions.getConstArray(); for( sal_Int32 nOption = 0; nOption < rMergeDescriptor.aPrintOptions.getLength(); ++nOption) { if( pPrintOptions[nOption].Name.equalsAscii( "CopyCount" ) ||( pPrintOptions[nOption].Name.equalsAscii( "FileName" )) ||( pPrintOptions[nOption].Name.equalsAscii( "Collate" )) ||( pPrintOptions[nOption].Name.equalsAscii( "Pages" )) ||( pPrintOptions[nOption].Name.equalsAscii( "Wait" ))) { aOptions.realloc( nOpts + 1 ); aOptions[ nOpts ].Name = pPrintOptions[nOption].Name; aOptions[ nOpts ].Value = pPrintOptions[nOption].Value ; } } // const SwModuleOptions * pModOpt = SW_MOD()->GetModuleConfig(); // if (pModOpt->IsSinglePrintJob()) // { // } // else // { pTargetView->ExecPrint( aOptions, IsMergeSilent(), rMergeDescriptor.bPrintAsync ); // } } xTargetDocShell->DoClose(); } //remove the temporary files ::std::vector::iterator aFileIter; for(aFileIter = aFilesToRemove.begin(); aFileIter != aFilesToRemove.end(); aFileIter++) SWUnoHelper::UCB_DeleteFile( *aFileIter ); // Alle Dispatcher freigeben pViewFrm = SfxViewFrame::GetFirst(pSourrceDocSh); while (pViewFrm) { pViewFrm->GetDispatcher()->Lock(sal_False); pViewFrm = SfxViewFrame::GetNext(*pViewFrm, pSourrceDocSh); } SW_MOD()->SetView(&pSourceShell->GetView()); } nMergeType = DBMGR_INSERT; } if(bEMail) { xMailDispatcher->stop(); xMailDispatcher->shutdown(); } return bLoop; } /*-------------------------------------------------------------------- Beschreibung: --------------------------------------------------------------------*/ IMPL_LINK_INLINE_START( SwNewDBMgr, PrtCancelHdl, Button *, pButton ) { pButton->GetParent()->Hide(); bCancel = sal_True; return 0; } IMPL_LINK_INLINE_END( SwNewDBMgr, PrtCancelHdl, Button *, pButton ) /*-------------------------------------------------------------------- Beschreibung: Numberformat der Spalte ermitteln und ggfs. in den uebergebenen Formatter uebertragen --------------------------------------------------------------------*/ sal_uLong SwNewDBMgr::GetColumnFmt( const String& rDBName, const String& rTableName, const String& rColNm, SvNumberFormatter* pNFmtr, long nLanguage ) { sal_uLong nRet = 0; if(pNFmtr) { uno::Reference< XDataSource> xSource; uno::Reference< XConnection> xConnection; sal_Bool bUseMergeData = sal_False; uno::Reference< XColumnsSupplier> xColsSupp; bool bDisposeConnection = false; if(pImpl->pMergeData && pImpl->pMergeData->sDataSource.equals(rDBName) && pImpl->pMergeData->sCommand.equals(rTableName)) { xConnection = pImpl->pMergeData->xConnection; xSource = SwNewDBMgr::getDataSourceAsParent(xConnection,rDBName); bUseMergeData = sal_True; xColsSupp = xColsSupp.query( pImpl->pMergeData->xResultSet ); } if(!xConnection.is()) { SwDBData aData; aData.sDataSource = rDBName; aData.sCommand = rTableName; aData.nCommandType = -1; SwDSParam* pParam = FindDSData(aData, sal_False); if(pParam && pParam->xConnection.is()) { xConnection = pParam->xConnection; xColsSupp = xColsSupp.query( pParam->xResultSet ); } else { rtl::OUString sDBName(rDBName); xConnection = RegisterConnection( sDBName ); bDisposeConnection = true; } if(bUseMergeData) pImpl->pMergeData->xConnection = xConnection; } bool bDispose = !xColsSupp.is(); if(bDispose) { xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName); } if(xColsSupp.is()) { uno::Reference xCols; try { xCols = xColsSupp->getColumns(); } catch(Exception&) { DBG_ERROR("Exception in getColumns()"); } if(!xCols.is() || !xCols->hasByName(rColNm)) return nRet; Any aCol = xCols->getByName(rColNm); uno::Reference< XPropertySet > xColumn; aCol >>= xColumn; nRet = GetColumnFmt(xSource, xConnection, xColumn, pNFmtr, nLanguage); if(bDispose) { ::comphelper::disposeComponent( xColsSupp ); } if(bDisposeConnection) { ::comphelper::disposeComponent( xConnection ); } } else nRet = pNFmtr->GetFormatIndex( NF_NUMBER_STANDARD, LANGUAGE_SYSTEM ); } return nRet; } /* -----------------------------07.06.01 15:43-------------------------------- ---------------------------------------------------------------------------*/ sal_uLong SwNewDBMgr::GetColumnFmt( uno::Reference< XDataSource> xSource, uno::Reference< XConnection> xConnection, uno::Reference< XPropertySet> xColumn, SvNumberFormatter* pNFmtr, long nLanguage ) { //JP 12.01.99: ggfs. das NumberFormat im Doc setzen sal_uLong nRet = 0; if(!xSource.is()) { uno::Reference xChild(xConnection, UNO_QUERY); if ( xChild.is() ) xSource = uno::Reference(xChild->getParent(), UNO_QUERY); } if(xSource.is() && xConnection.is() && xColumn.is() && pNFmtr) { SvNumberFormatsSupplierObj* pNumFmt = new SvNumberFormatsSupplierObj( pNFmtr ); uno::Reference< util::XNumberFormatsSupplier > xDocNumFmtsSupplier = pNumFmt; uno::Reference< XNumberFormats > xDocNumberFormats = xDocNumFmtsSupplier->getNumberFormats(); uno::Reference< XNumberFormatTypes > xDocNumberFormatTypes(xDocNumberFormats, UNO_QUERY); Locale aLocale( MsLangId::convertLanguageToLocale( (LanguageType)nLanguage )); //get the number formatter of the data source uno::Reference xSourceProps(xSource, UNO_QUERY); uno::Reference< XNumberFormats > xNumberFormats; if(xSourceProps.is()) { Any aFormats = xSourceProps->getPropertyValue(C2U("NumberFormatsSupplier")); if(aFormats.hasValue()) { uno::Reference xSuppl; aFormats >>= xSuppl; if(xSuppl.is()) { xNumberFormats = xSuppl->getNumberFormats(); } } } bool bUseDefault = true; try { Any aFormatKey = xColumn->getPropertyValue(C2U("FormatKey")); if(aFormatKey.hasValue()) { sal_Int32 nFmt = 0; aFormatKey >>= nFmt; if(xNumberFormats.is()) { try { uno::Reference xNumProps = xNumberFormats->getByKey( nFmt ); Any aFormatString = xNumProps->getPropertyValue(C2U("FormatString")); Any aLocaleVal = xNumProps->getPropertyValue(C2U("Locale")); rtl::OUString sFormat; aFormatString >>= sFormat; lang::Locale aLoc; aLocaleVal >>= aLoc; nFmt = xDocNumberFormats->queryKey( sFormat, aLoc, sal_False ); if(NUMBERFORMAT_ENTRY_NOT_FOUND == sal::static_int_cast< sal_uInt32, sal_Int32>(nFmt)) nFmt = xDocNumberFormats->addNew( sFormat, aLoc ); nRet = nFmt; bUseDefault = false; } catch(const Exception&) { DBG_ERROR("illegal number format key"); } } } } catch( const Exception& ) { DBG_ERROR("no FormatKey property found"); } if(bUseDefault) nRet = SwNewDBMgr::GetDbtoolsClient().getDefaultNumberFormat(xColumn, xDocNumberFormatTypes, aLocale); } return nRet; } /* -----------------------------17.07.00 09:47-------------------------------- ---------------------------------------------------------------------------*/ sal_Int32 SwNewDBMgr::GetColumnType( const String& rDBName, const String& rTableName, const String& rColNm ) { sal_Int32 nRet = DataType::SQLNULL; SwDBData aData; aData.sDataSource = rDBName; aData.sCommand = rTableName; aData.nCommandType = -1; SwDSParam* pParam = FindDSData(aData, sal_False); uno::Reference< XConnection> xConnection; uno::Reference< XColumnsSupplier > xColsSupp; bool bDispose = false; if(pParam && pParam->xConnection.is()) { xConnection = pParam->xConnection; xColsSupp = uno::Reference< XColumnsSupplier >( pParam->xResultSet, UNO_QUERY ); } else { rtl::OUString sDBName(rDBName); xConnection = RegisterConnection( sDBName ); } if( !xColsSupp.is() ) { xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName); bDispose = true; } if(xColsSupp.is()) { uno::Reference xCols = xColsSupp->getColumns(); if(xCols->hasByName(rColNm)) { Any aCol = xCols->getByName(rColNm); uno::Reference xCol; aCol >>= xCol; Any aType = xCol->getPropertyValue(C2S("Type")); aType >>= nRet; } if(bDispose) ::comphelper::disposeComponent( xColsSupp ); } return nRet; } /* -----------------------------03.07.00 17:12-------------------------------- ---------------------------------------------------------------------------*/ uno::Reference< sdbc::XConnection> SwNewDBMgr::GetConnection(const String& rDataSource, uno::Reference& rxSource) { Reference< sdbc::XConnection> xConnection; Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); try { Reference xComplConnection(SwNewDBMgr::GetDbtoolsClient().getDataSource(rDataSource, xMgr),UNO_QUERY); if ( xComplConnection.is() ) { rxSource.set(xComplConnection,UNO_QUERY); Reference< XInteractionHandler > xHandler( xMgr->createInstance( C2U( "com.sun.star.task.InteractionHandler" )), UNO_QUERY); xConnection = xComplConnection->connectWithCompletion( xHandler ); } } catch(Exception&) {} return xConnection; } /* -----------------------------03.07.00 17:12-------------------------------- ---------------------------------------------------------------------------*/ uno::Reference< sdbcx::XColumnsSupplier> SwNewDBMgr::GetColumnSupplier(uno::Reference xConnection, const String& rTableOrQuery, sal_uInt8 eTableOrQuery) { Reference< sdbcx::XColumnsSupplier> xRet; try { if(eTableOrQuery == SW_DB_SELECT_UNKNOWN) { //search for a table with the given command name Reference xTSupplier = Reference(xConnection, UNO_QUERY); if(xTSupplier.is()) { Reference xTbls = xTSupplier->getTables(); eTableOrQuery = xTbls->hasByName(rTableOrQuery) ? SW_DB_SELECT_TABLE : SW_DB_SELECT_QUERY; } } sal_Int32 nCommandType = SW_DB_SELECT_TABLE == eTableOrQuery ? CommandType::TABLE : CommandType::QUERY; Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); Reference xRowSet( xMgr->createInstance(C2U("com.sun.star.sdb.RowSet")), UNO_QUERY); ::rtl::OUString sDataSource; Reference xSource = SwNewDBMgr::getDataSourceAsParent(xConnection, sDataSource); Reference xSourceProperties(xSource, UNO_QUERY); if(xSourceProperties.is()) { xSourceProperties->getPropertyValue(C2U("Name")) >>= sDataSource; } Reference xRowProperties(xRowSet, UNO_QUERY); xRowProperties->setPropertyValue(C2U("DataSourceName"), makeAny(sDataSource)); xRowProperties->setPropertyValue(C2U("Command"), makeAny(::rtl::OUString(rTableOrQuery))); xRowProperties->setPropertyValue(C2U("CommandType"), makeAny(nCommandType)); xRowProperties->setPropertyValue(C2U("FetchSize"), makeAny((sal_Int32)10)); xRowProperties->setPropertyValue(C2U("ActiveConnection"), makeAny(xConnection)); xRowSet->execute(); xRet = Reference( xRowSet, UNO_QUERY ); } catch( const uno::Exception& ) { DBG_ERROR("Exception in SwDBMgr::GetColumnSupplier"); } return xRet; } /* -----------------------------05.07.00 13:44-------------------------------- ---------------------------------------------------------------------------*/ String SwNewDBMgr::GetDBField(uno::Reference xColumnProps, const SwDBFormatData& rDBFormatData, double* pNumber) { uno::Reference< XColumn > xColumn(xColumnProps, UNO_QUERY); String sRet; DBG_ASSERT(xColumn.is(), "SwNewDBMgr::::ImportDBField: illegal arguments"); if(!xColumn.is()) return sRet; Any aType = xColumnProps->getPropertyValue(C2U("Type")); sal_Int32 eDataType = 0; aType >>= eDataType; switch(eDataType) { case DataType::CHAR: case DataType::VARCHAR: case DataType::LONGVARCHAR: try { sRet = xColumn->getString(); } catch( SQLException& ) { } break; case DataType::BIT: case DataType::BOOLEAN: case DataType::TINYINT: case DataType::SMALLINT: case DataType::INTEGER: case DataType::BIGINT: case DataType::FLOAT: case DataType::REAL: case DataType::DOUBLE: case DataType::NUMERIC: case DataType::DECIMAL: case DataType::DATE: case DataType::TIME: case DataType::TIMESTAMP: { // ::Date aTempDate(rDBFormatData.aNullDate.Day, // rDBFormatData.aNullDate.Month, rDBFormatData.aNullDate.Year); try { SwDbtoolsClient& aClient = SwNewDBMgr::GetDbtoolsClient(); sRet = aClient.getFormattedValue( xColumnProps, rDBFormatData.xFormatter, rDBFormatData.aLocale, rDBFormatData.aNullDate); if (pNumber) { double fVal = xColumn->getDouble(); if(!xColumn->wasNull()) { *pNumber = fVal; } } } catch(Exception& ) { DBG_ERROR("exception caught"); } } break; // case DataType::BINARY: // case DataType::VARBINARY: // case DataType::LONGVARBINARY: // case DataType::SQLNULL: // case DataType::OTHER: // case DataType::OBJECT: // case DataType::DISTINCT: // case DataType::STRUCT: // case DataType::ARRAY: // case DataType::BLOB: // case DataType::CLOB: // case DataType::REF: // default: } // if (pFormat) // { // SFX_ITEMSET_GET(*pCol, pFormatItem, SfxUInt32Item, SBA_DEF_FMTVALUE, sal_True); // *pFormat = pFormatItem->GetValue(); // } return sRet; } /* -----------------------------06.07.00 14:28-------------------------------- releases the merge data source table or query after merge is completed ---------------------------------------------------------------------------*/ void SwNewDBMgr::EndMerge() { DBG_ASSERT(bInMerge, "merge is not active"); bInMerge = sal_False; delete pImpl->pMergeData; pImpl->pMergeData = 0; } /* -----------------------------06.07.00 14:28-------------------------------- checks if a desired data source table or query is open ---------------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::IsDataSourceOpen(const String& rDataSource, const String& rTableOrQuery, sal_Bool bMergeOnly) { if(pImpl->pMergeData) { return !bMergeLock && ((rDataSource == (String)pImpl->pMergeData->sDataSource && rTableOrQuery == (String)pImpl->pMergeData->sCommand) ||(!rDataSource.Len() && !rTableOrQuery.Len())) && pImpl->pMergeData->xResultSet.is(); } else if(!bMergeOnly) { SwDBData aData; aData.sDataSource = rDataSource; aData.sCommand = rTableOrQuery; aData.nCommandType = -1; SwDSParam* pFound = FindDSData(aData, sal_False); return (pFound && pFound->xResultSet.is()); } return sal_False; } /* -----------------------------17.07.00 16:44-------------------------------- read column data a a specified position ---------------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::GetColumnCnt(const String& rSourceName, const String& rTableName, const String& rColumnName, sal_uInt32 nAbsRecordId, long nLanguage, String& rResult, double* pNumber) { sal_Bool bRet = sal_False; SwDSParam* pFound = 0; //check if it's the merge data source if(pImpl->pMergeData && rSourceName == (String)pImpl->pMergeData->sDataSource && rTableName == (String)pImpl->pMergeData->sCommand) { pFound = pImpl->pMergeData; } else { SwDBData aData; aData.sDataSource = rSourceName; aData.sCommand = rTableName; aData.nCommandType = -1; pFound = FindDSData(aData, sal_False); } //check validity of supplied record Id if(pFound->aSelection.getLength()) { //the destination has to be an element of the selection const Any* pSelection = pFound->aSelection.getConstArray(); sal_Bool bFound = sal_False; for(sal_Int32 nPos = 0; !bFound && nPos < pFound->aSelection.getLength(); nPos++) { sal_Int32 nSelection = 0; pSelection[nPos] >>= nSelection; if(nSelection == static_cast(nAbsRecordId)) bFound = sal_True; } if(!bFound) return sal_False; } if(pFound && pFound->xResultSet.is() && !pFound->bAfterSelection) { sal_Int32 nOldRow = 0; try { nOldRow = pFound->xResultSet->getRow(); } catch(const Exception& ) { return sal_False; } //position to the desired index sal_Bool bMove = sal_True; if ( nOldRow != static_cast(nAbsRecordId) ) bMove = lcl_MoveAbsolute(pFound, nAbsRecordId); if(bMove) { bRet = lcl_GetColumnCnt(pFound, rColumnName, nLanguage, rResult, pNumber); } if ( nOldRow != static_cast(nAbsRecordId) ) bMove = lcl_MoveAbsolute(pFound, nOldRow); } return bRet; } /* -----------------------------06.07.00 16:47-------------------------------- reads the column data at the current position ---------------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::GetMergeColumnCnt(const String& rColumnName, sal_uInt16 nLanguage, String &rResult, double *pNumber, sal_uInt32 * /*pFormat*/) { if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is() || pImpl->pMergeData->bAfterSelection ) { rResult.Erase(); return sal_False; } sal_Bool bRet = lcl_GetColumnCnt(pImpl->pMergeData, rColumnName, nLanguage, rResult, pNumber); return bRet; } /* -----------------------------07.07.00 14:28-------------------------------- ---------------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::ToNextMergeRecord() { DBG_ASSERT(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge"); return ToNextRecord(pImpl->pMergeData); } /* -----------------------------10.07.01 14:28-------------------------------- ---------------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::ToNextRecord( const String& rDataSource, const String& rCommand, sal_Int32 /*nCommandType*/) { SwDSParam* pFound = 0; if(pImpl->pMergeData && rDataSource == (String)pImpl->pMergeData->sDataSource && rCommand == (String)pImpl->pMergeData->sCommand) pFound = pImpl->pMergeData; else { SwDBData aData; aData.sDataSource = rDataSource; aData.sCommand = rCommand; aData.nCommandType = -1; pFound = FindDSData(aData, sal_False); } return ToNextRecord(pFound); } /* -----------------------------10.07.01 14:38-------------------------------- ---------------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::ToNextRecord(SwDSParam* pParam) { sal_Bool bRet = sal_True; if(!pParam || !pParam->xResultSet.is() || pParam->bEndOfDB || (pParam->aSelection.getLength() && pParam->aSelection.getLength() <= pParam->nSelectionIndex)) { if(pParam) pParam->CheckEndOfDB(); return sal_False; } try { if(pParam->aSelection.getLength()) { sal_Int32 nPos = 0; pParam->aSelection.getConstArray()[ pParam->nSelectionIndex++ ] >>= nPos; pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos ); pParam->CheckEndOfDB(); bRet = !pParam->bEndOfDB; if(pParam->nSelectionIndex >= pParam->aSelection.getLength()) pParam->bEndOfDB = sal_True; } else { sal_Int32 nBefore = pParam->xResultSet->getRow(); pParam->bEndOfDB = !pParam->xResultSet->next(); if( !pParam->bEndOfDB && nBefore == pParam->xResultSet->getRow()) { //next returned true but it didn't move pParam->bEndOfDB = sal_True; } pParam->CheckEndOfDB(); bRet = !pParam->bEndOfDB; ++pParam->nSelectionIndex; } } catch(Exception&) { } return bRet; } /* -----------------------------13.07.00 17:23-------------------------------- synchronized labels contain a next record field at their end to assure that the next page can be created in mail merge the cursor position must be validated ---------------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::ExistsNextRecord() const { return pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB; } /* -----------------------------13.07.00 10:41-------------------------------- ---------------------------------------------------------------------------*/ sal_uInt32 SwNewDBMgr::GetSelectedRecordId() { sal_uInt32 nRet = 0; DBG_ASSERT(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge"); if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is()) return sal_False; try { nRet = pImpl->pMergeData->xResultSet->getRow(); } catch(Exception& ) { } return nRet; } /* -----------------------------13.07.00 10:58-------------------------------- ---------------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::ToRecordId(sal_Int32 nSet) { DBG_ASSERT(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge"); if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is()|| nSet < 0) return sal_False; sal_Bool bRet = sal_False; sal_Int32 nAbsPos = nSet; if(nAbsPos >= 0) { bRet = lcl_MoveAbsolute(pImpl->pMergeData, nAbsPos); pImpl->pMergeData->bEndOfDB = !bRet; pImpl->pMergeData->CheckEndOfDB(); } return bRet; } /* -----------------------------17.07.00 14:17-------------------------------- ---------------------------------------------------------------------------*/ sal_Bool SwNewDBMgr::OpenDataSource(const String& rDataSource, const String& rTableOrQuery, sal_Int32 nCommandType, bool bCreate) { SwDBData aData; aData.sDataSource = rDataSource; aData.sCommand = rTableOrQuery; aData.nCommandType = nCommandType; SwDSParam* pFound = FindDSData(aData, sal_True); uno::Reference< XDataSource> xSource; if(pFound->xResultSet.is()) return sal_True; SwDSParam* pParam = FindDSConnection(rDataSource, sal_False); uno::Reference< XConnection> xConnection; if(pParam && pParam->xConnection.is()) pFound->xConnection = pParam->xConnection; else if(bCreate) { rtl::OUString sDataSource(rDataSource); pFound->xConnection = RegisterConnection( sDataSource ); } if(pFound->xConnection.is()) { try { uno::Reference< sdbc::XDatabaseMetaData > xMetaData = pFound->xConnection->getMetaData(); try { pFound->bScrollable = xMetaData ->supportsResultSetType((sal_Int32)ResultSetType::SCROLL_INSENSITIVE); } catch(Exception&) { //#98373# DB driver may not be ODBC 3.0 compliant pFound->bScrollable = sal_True; } pFound->xStatement = pFound->xConnection->createStatement(); rtl::OUString aQuoteChar = xMetaData->getIdentifierQuoteString(); rtl::OUString sStatement(C2U("SELECT * FROM ")); sStatement = C2U("SELECT * FROM "); sStatement += aQuoteChar; sStatement += rTableOrQuery; sStatement += aQuoteChar; pFound->xResultSet = pFound->xStatement->executeQuery( sStatement ); //after executeQuery the cursor must be positioned pFound->bEndOfDB = !pFound->xResultSet->next(); pFound->bAfterSelection = sal_False; pFound->CheckEndOfDB(); ++pFound->nSelectionIndex; } catch (Exception&) { pFound->xResultSet = 0; pFound->xStatement = 0; pFound->xConnection = 0; } } return pFound->xResultSet.is(); } /* -----------------------------14.08.2001 10:26------------------------------ ---------------------------------------------------------------------------*/ uno::Reference< XConnection> SwNewDBMgr::RegisterConnection(rtl::OUString& rDataSource) { SwDSParam* pFound = SwNewDBMgr::FindDSConnection(rDataSource, sal_True); uno::Reference< XDataSource> xSource; if(!pFound->xConnection.is()) { pFound->xConnection = SwNewDBMgr::GetConnection(rDataSource, xSource ); try { uno::Reference xComponent(pFound->xConnection, UNO_QUERY); if(xComponent.is()) xComponent->addEventListener(pImpl->xDisposeListener); } catch(Exception&) { } } return pFound->xConnection; } /* -----------------------------17.07.00 15:55-------------------------------- ---------------------------------------------------------------------------*/ sal_uInt32 SwNewDBMgr::GetSelectedRecordId( const String& rDataSource, const String& rTableOrQuery, sal_Int32 nCommandType) { sal_uInt32 nRet = 0xffffffff; //check for merge data source first if(pImpl->pMergeData && rDataSource == (String)pImpl->pMergeData->sDataSource && rTableOrQuery == (String)pImpl->pMergeData->sCommand && (nCommandType == -1 || nCommandType == pImpl->pMergeData->nCommandType) && pImpl->pMergeData->xResultSet.is()) nRet = GetSelectedRecordId(); else { SwDBData aData; aData.sDataSource = rDataSource; aData.sCommand = rTableOrQuery; aData.nCommandType = nCommandType; SwDSParam* pFound = FindDSData(aData, sal_False); if(pFound && pFound->xResultSet.is()) { try { //if a selection array is set the current row at the result set may not be set yet if(pFound->aSelection.getLength()) { sal_Int32 nSelIndex = pFound->nSelectionIndex; if(nSelIndex >= pFound->aSelection.getLength()) nSelIndex = pFound->aSelection.getLength() -1; pFound->aSelection.getConstArray()[nSelIndex] >>= nRet; } else nRet = pFound->xResultSet->getRow(); } catch(Exception&){} } } return nRet; } /* -----------------------------17.07.00 14:18-------------------------------- close all data sources - after fields were updated ---------------------------------------------------------------------------*/ void SwNewDBMgr::CloseAll(sal_Bool bIncludingMerge) { //the only thing done here is to reset the selection index //all connections stay open for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.Count(); nPos++) { SwDSParam* pParam = aDataSourceParams[nPos]; if(bIncludingMerge || pParam != pImpl->pMergeData) { pParam->nSelectionIndex = 0; pParam->bAfterSelection = sal_False; pParam->bEndOfDB = sal_False; try { if(!bInMerge && pParam->xResultSet.is()) pParam->xResultSet->first(); } catch(Exception& ) {} } } } /* -----------------------------17.07.00 14:54-------------------------------- ---------------------------------------------------------------------------*/ SwDSParam* SwNewDBMgr::FindDSData(const SwDBData& rData, sal_Bool bCreate) { //prefer merge data if available if(pImpl->pMergeData && rData.sDataSource == pImpl->pMergeData->sDataSource && rData.sCommand == pImpl->pMergeData->sCommand && (rData.nCommandType == -1 || rData.nCommandType == pImpl->pMergeData->nCommandType || (bCreate && pImpl->pMergeData->nCommandType == -1))) { return pImpl->pMergeData; } SwDSParam* pFound = 0; for(sal_uInt16 nPos = aDataSourceParams.Count(); nPos; nPos--) { SwDSParam* pParam = aDataSourceParams[nPos - 1]; if(rData.sDataSource == pParam->sDataSource && rData.sCommand == pParam->sCommand && (rData.nCommandType == -1 || rData.nCommandType == pParam->nCommandType || (bCreate && pParam->nCommandType == -1))) { //#94779# calls from the calculator may add a connection with an invalid commandtype //later added "real" data base connections have to re-use the already available //DSData and set the correct CommandType if(bCreate && pParam->nCommandType == -1) pParam->nCommandType = rData.nCommandType; pFound = pParam; break; } } if(bCreate) { if(!pFound) { pFound = new SwDSParam(rData); aDataSourceParams.Insert(pFound, aDataSourceParams.Count()); try { uno::Reference xComponent(pFound->xConnection, UNO_QUERY); if(xComponent.is()) xComponent->addEventListener(pImpl->xDisposeListener); } catch(Exception&) { } } } return pFound; } /* -----------------------------14.08.2001 10:27------------------------------ ---------------------------------------------------------------------------*/ SwDSParam* SwNewDBMgr::FindDSConnection(const rtl::OUString& rDataSource, sal_Bool bCreate) { //prefer merge data if available if(pImpl->pMergeData && rDataSource == pImpl->pMergeData->sDataSource ) { return pImpl->pMergeData; } SwDSParam* pFound = 0; for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.Count(); nPos++) { SwDSParam* pParam = aDataSourceParams[nPos]; if(rDataSource == pParam->sDataSource) { pFound = pParam; break; } } if(bCreate && !pFound) { SwDBData aData; aData.sDataSource = rDataSource; pFound = new SwDSParam(aData); aDataSourceParams.Insert(pFound, aDataSourceParams.Count()); try { uno::Reference xComponent(pFound->xConnection, UNO_QUERY); if(xComponent.is()) xComponent->addEventListener(pImpl->xDisposeListener); } catch(Exception&) { } } return pFound; } /* -----------------------------17.07.00 14:34-------------------------------- ---------------------------------------------------------------------------*/ const SwDBData& SwNewDBMgr::GetAddressDBName() { return SW_MOD()->GetDBConfig()->GetAddressSource(); } /* -----------------------------18.07.00 13:13-------------------------------- ---------------------------------------------------------------------------*/ Sequence SwNewDBMgr::GetExistingDatabaseNames() { uno::Reference xDBContext; uno::Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); if( xMgr.is() ) { uno::Reference xInstance = xMgr->createInstance( C2U( "com.sun.star.sdb.DatabaseContext" )); xDBContext = uno::Reference(xInstance, UNO_QUERY) ; } if(xDBContext.is()) { return xDBContext->getElementNames(); } return Sequence(); } /*-- 26.05.2004 14:33:13--------------------------------------------------- -----------------------------------------------------------------------*/ String SwNewDBMgr::LoadAndRegisterDataSource() { sfx2::FileDialogHelper aDlgHelper( TemplateDescription::FILEOPEN_SIMPLE, 0 ); Reference < XFilePicker > xFP = aDlgHelper.GetFilePicker(); String sHomePath(SvtPathOptions().GetWorkPath()); aDlgHelper.SetDisplayDirectory( sHomePath ); Reference xFltMgr(xFP, UNO_QUERY); String sFilterAll(SW_RES(STR_FILTER_ALL)); String sFilterAllData(SW_RES(STR_FILTER_ALL_DATA)); String sFilterSXB(SW_RES(STR_FILTER_SXB)); String sFilterSXC(SW_RES(STR_FILTER_SXC)); String sFilterDBF(SW_RES(STR_FILTER_DBF)); String sFilterXLS(SW_RES(STR_FILTER_XLS)); String sFilterTXT(SW_RES(STR_FILTER_TXT)); String sFilterCSV(SW_RES(STR_FILTER_CSV)); #ifdef WNT String sFilterMDB(SW_RES(STR_FILTER_MDB)); String sFilterACCDB(SW_RES(STR_FILTER_ACCDB)); #endif xFltMgr->appendFilter( sFilterAll, C2U("*") ); xFltMgr->appendFilter( sFilterAllData, C2U("*.ods;*.sxc;*.dbf;*.xls;*.txt;*.csv")); xFltMgr->appendFilter( sFilterSXB, C2U("*.odb") ); xFltMgr->appendFilter( sFilterSXC, C2U("*.ods;*.sxc") ); xFltMgr->appendFilter( sFilterDBF, C2U("*.dbf") ); xFltMgr->appendFilter( sFilterXLS, C2U("*.xls") ); xFltMgr->appendFilter( sFilterTXT, C2U("*.txt") ); xFltMgr->appendFilter( sFilterCSV, C2U("*.csv") ); #ifdef WNT xFltMgr->appendFilter( sFilterMDB, C2U("*.mdb") ); xFltMgr->appendFilter( sFilterACCDB, C2U("*.accdb") ); #endif xFltMgr->setCurrentFilter( sFilterAll ) ; String sFind; bool bTextConnection = false; if( ERRCODE_NONE == aDlgHelper.Execute() ) { String sURL = xFP->getFiles().getConstArray()[0]; //data sources have to be registered depending on their extensions INetURLObject aURL( sURL ); String sExt( aURL.GetExtension() ); Any aURLAny; Any aTableFilterAny; Any aSuppressVersionsAny; Any aInfoAny; INetURLObject aTempURL(aURL); bool bStore = true; if(sExt.EqualsAscii("odb")) { bStore = false; } else if(sExt.EqualsIgnoreCaseAscii("sxc") || sExt.EqualsIgnoreCaseAscii("ods") || sExt.EqualsIgnoreCaseAscii("xls")) { rtl::OUString sDBURL(C2U("sdbc:calc:")); sDBURL += aTempURL.GetMainURL(INetURLObject::NO_DECODE); aURLAny <<= sDBURL; } else if(sExt.EqualsIgnoreCaseAscii("dbf")) { aTempURL.removeSegment(); aTempURL.removeFinalSlash(); rtl::OUString sDBURL(C2U("sdbc:dbase:")); sDBURL += aTempURL.GetMainURL(INetURLObject::NO_DECODE); aURLAny <<= sDBURL; //set the filter to the file name without extension Sequence aFilters(1); rtl::OUString sTmp(aURL.getBase()); aFilters[0] = aURL.getBase(); aTableFilterAny <<= aFilters; } else if(sExt.EqualsIgnoreCaseAscii("csv") || sExt.EqualsIgnoreCaseAscii("txt")) { aTempURL.removeSegment(); aTempURL.removeFinalSlash(); rtl::OUString sDBURL(C2U("sdbc:flat:")); //only the 'path' has to be added sDBURL += aTempURL.GetMainURL(INetURLObject::NO_DECODE); aURLAny <<= sDBURL; bTextConnection = true; //set the filter to the file name without extension Sequence aFilters(1); rtl::OUString sTmp(aURL.getBase()); aFilters[0] = aURL.getBase(); aTableFilterAny <<= aFilters; } #ifdef WNT else if(sExt.EqualsIgnoreCaseAscii("mdb")) { rtl::OUString sDBURL(C2U("sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=")); sDBURL += aTempURL.PathToFileName(); aURLAny <<= sDBURL; aSuppressVersionsAny <<= makeAny(true); } else if(sExt.EqualsIgnoreCaseAscii("accdb")) { rtl::OUString sDBURL(C2U("sdbc:ado:PROVIDER=Microsoft.ACE.OLEDB.12.0;DATA SOURCE=")); sDBURL += aTempURL.PathToFileName(); aURLAny <<= sDBURL; aSuppressVersionsAny <<= makeAny(true); } #endif try { Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); Reference xInstance = xMgr->createInstance( C2U( "com.sun.star.sdb.DatabaseContext" )); Reference xDBContext(xInstance, UNO_QUERY_THROW); Reference xFact( xDBContext, UNO_QUERY); String sNewName = INetURLObject::decode( aURL.getName(), INET_HEX_ESCAPE, INetURLObject::DECODE_UNAMBIGUOUS, RTL_TEXTENCODING_UTF8 ); xub_StrLen nExtLen = static_cast< xub_StrLen >(aURL.GetExtension().getLength()); sNewName.Erase( sNewName.Len() - nExtLen - 1, nExtLen + 1 ); //find a unique name if sNewName already exists sFind = sNewName; sal_Int32 nIndex = 0; while(xDBContext->hasByName(sFind)) { sFind = sNewName; sFind += String::CreateFromInt32(++nIndex); } Reference xNewInstance; if(!bStore) { //odb-file Any aDataSource = xDBContext->getByName(aTempURL.GetMainURL(INetURLObject::NO_DECODE)); aDataSource >>= xNewInstance; } else { xNewInstance = xFact->createInstance(); Reference xDataProperties(xNewInstance, UNO_QUERY); if(aURLAny.hasValue()) xDataProperties->setPropertyValue(C2U("URL"), aURLAny); if(aTableFilterAny.hasValue()) xDataProperties->setPropertyValue(C2U("TableFilter"), aTableFilterAny); if(aSuppressVersionsAny.hasValue()) xDataProperties->setPropertyValue(C2U("SuppressVersionColumns"), aSuppressVersionsAny); if(aInfoAny.hasValue()) xDataProperties->setPropertyValue(C2U("Info"), aInfoAny); if( bTextConnection ) { uno::Reference < ui::dialogs::XExecutableDialog > xSettingsDlg( xMgr->createInstance( C2U( "com.sun.star.sdb.TextConnectionSettings" ) ), uno::UNO_QUERY); if( xSettingsDlg->execute() ) { uno::Any aSettings = xDataProperties->getPropertyValue( C2U( "Settings" ) ); uno::Reference < beans::XPropertySet > xDSSettings; aSettings >>= xDSSettings; ::comphelper::copyProperties( uno::Reference < beans::XPropertySet >( xSettingsDlg, uno::UNO_QUERY ), xDSSettings ); xDSSettings->setPropertyValue( C2U("Extension"), uno::makeAny( ::rtl::OUString( sExt ))); } } Reference xDS(xNewInstance, UNO_QUERY_THROW); Reference xStore(xDS->getDatabaseDocument(), UNO_QUERY_THROW); String sOutputExt = String::CreateFromAscii(".odb"); String sTmpName; { utl::TempFile aTempFile(sNewName , &sOutputExt, &sHomePath); aTempFile.EnableKillingFile(sal_True); sTmpName = aTempFile.GetURL(); } xStore->storeAsURL(sTmpName, Sequence< PropertyValue >()); } Reference xNaming(xDBContext, UNO_QUERY); xNaming->registerObject( sFind, xNewInstance ); } catch(Exception&) { } } return sFind; } /* -----------------------------10.11.00 17:10-------------------------------- ---------------------------------------------------------------------------*/ void SwNewDBMgr::ExecuteFormLetter( SwWrtShell& rSh, const Sequence& rProperties, sal_Bool bWithDataSourceBrowser) { //prevent second call if(pImpl->pMergeDialog) return ; rtl::OUString sDataSource, sDataTableOrQuery; Sequence aSelection; sal_Int32 nCmdType = CommandType::TABLE; uno::Reference< XConnection> xConnection; ODataAccessDescriptor aDescriptor(rProperties); sDataSource = aDescriptor.getDataSource(); aDescriptor[daCommand] >>= sDataTableOrQuery; aDescriptor[daCommandType] >>= nCmdType; if ( aDescriptor.has(daSelection) ) aDescriptor[daSelection] >>= aSelection; if ( aDescriptor.has(daConnection) ) aDescriptor[daConnection] >>= xConnection; if(!sDataSource.getLength() || !sDataTableOrQuery.getLength()) { DBG_ERROR("PropertyValues missing or unset"); return; } //always create a connection for the dialog and dispose it after the dialog has been closed SwDSParam* pFound = 0; if(!xConnection.is()) { xConnection = SwNewDBMgr::RegisterConnection(sDataSource); pFound = FindDSConnection(sDataSource, sal_True); } SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); DBG_ASSERT(pFact, "Dialogdiet fail!"); pImpl->pMergeDialog = pFact->CreateMailMergeDlg( DLG_MAILMERGE, &rSh.GetView().GetViewFrame()->GetWindow(), rSh, sDataSource, sDataTableOrQuery, nCmdType, xConnection, bWithDataSourceBrowser ? 0 : &aSelection); DBG_ASSERT(pImpl->pMergeDialog, "Dialogdiet fail!"); if(pImpl->pMergeDialog->Execute() == RET_OK) { aDescriptor[daSelection] <<= pImpl->pMergeDialog->GetSelection(); uno::Reference xResSet = pImpl->pMergeDialog->GetResultSet(); if(xResSet.is()) aDescriptor[daCursor] <<= xResSet; // SfxObjectShellRef is ok, since there should be no control over the document lifetime here SfxObjectShellRef xDocShell = rSh.GetView().GetViewFrame()->GetObjectShell(); SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE), xDocShell)); { //copy rSh to aTempFile ::rtl::OUString sTempURL; const SfxFilter *pSfxFlt = SwIoSystem::GetFilterOfFormat( String::CreateFromAscii( FILTER_XML ), SwDocShell::Factory().GetFilterContainer() ); try { uno::Sequence< beans::PropertyValue > aValues(1); beans::PropertyValue* pValues = aValues.getArray(); pValues[0].Name = C2U("FilterName"); pValues[0].Value <<= ::rtl::OUString(pSfxFlt->GetFilterName()); uno::Reference< frame::XStorable > xStore( xDocShell->GetModel(), uno::UNO_QUERY); sTempURL = URIHelper::SmartRel2Abs( INetURLObject(), utl::TempFile::CreateTempName() ); xStore->storeToURL( sTempURL, aValues ); } catch( const uno::Exception& rEx ) { (void) rEx; } if( xDocShell->GetError() ) { // error message ?? ErrorHandler::HandleError( xDocShell->GetError() ); } else { // the shell will be explicitly closed, but it is more safe to use SfxObjectShellLock here // especially for the case that the loading has failed SfxObjectShellLock xWorkDocSh( new SwDocShell( SFX_CREATE_MODE_INTERNAL )); SfxMedium* pWorkMed = new SfxMedium( sTempURL, STREAM_STD_READ, sal_True ); pWorkMed->SetFilter( pSfxFlt ); if( xWorkDocSh->DoLoad(pWorkMed) ) { SfxViewFrame *pFrame = SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 ); SwView *pView = (SwView*) pFrame->GetViewShell(); pView->AttrChangedNotify( &pView->GetWrtShell() );//Damit SelectShell gerufen wird. //set the current DBMgr SwDoc* pWorkDoc = pView->GetWrtShell().GetDoc(); SwNewDBMgr* pWorkDBMgr = pWorkDoc->GetNewDBMgr(); pWorkDoc->SetNewDBMgr( this ); SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), pView->GetWrtShell(), aDescriptor ); aMergeDesc.sSaveToFilter = pImpl->pMergeDialog->GetSaveFilter(); aMergeDesc.bCreateSingleFile = !pImpl->pMergeDialog->IsSaveIndividualDocs(); if( !aMergeDesc.bCreateSingleFile && pImpl->pMergeDialog->IsGenerateFromDataBase() ) { aMergeDesc.sAddressFromColumn = pImpl->pMergeDialog->GetColumnName(); aMergeDesc.sSubject = pImpl->pMergeDialog->GetPath(); } MergeNew(aMergeDesc); pWorkDoc->SetNewDBMgr( pWorkDBMgr ); //close the temporary file uno::Reference< util::XCloseable > xClose( xWorkDocSh->GetModel(), uno::UNO_QUERY ); if (xClose.is()) { try { //! 'sal_True' -> transfer ownership to vetoing object if vetoed! //! I.e. now that object is responsible for closing the model and doc shell. xClose->close( sal_True ); } catch ( const uno::Exception& ) { } } } } //remove the temporary file SWUnoHelper::UCB_DeleteFile( sTempURL ); } SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE_END, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END), rSh.GetView().GetViewFrame()->GetObjectShell())); // reset the cursor inside xResSet = NULL; aDescriptor[daCursor] <<= xResSet; } if(pFound) { for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.Count(); nPos++) { SwDSParam* pParam = aDataSourceParams[nPos]; if(pParam == pFound) { try { uno::Reference xComp(pParam->xConnection, UNO_QUERY); if(xComp.is()) xComp->dispose(); } catch(const RuntimeException& ) { //may be disposed already since multiple entries may have used the same connection } break; } //pFound doesn't need to be removed/deleted - //this has been done by the SwConnectionDisposedListener_Impl already } } DELETEZ(pImpl->pMergeDialog); } /* -----------------------------13.11.00 08:20-------------------------------- ---------------------------------------------------------------------------*/ void SwNewDBMgr::InsertText(SwWrtShell& rSh, const Sequence< PropertyValue>& rProperties) { rtl::OUString sDataSource, sDataTableOrQuery; uno::Reference xResSet; Sequence aSelection; sal_Bool bHasSelectionProperty = sal_False; sal_Int32 nSelectionPos = 0; sal_Int16 nCmdType = CommandType::TABLE; const PropertyValue* pValues = rProperties.getConstArray(); uno::Reference< XConnection> xConnection; for(sal_Int32 nPos = 0; nPos < rProperties.getLength(); nPos++) { if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cDataSourceName))) pValues[nPos].Value >>= sDataSource; else if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cCommand))) pValues[nPos].Value >>= sDataTableOrQuery; else if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cCursor))) pValues[nPos].Value >>= xResSet; else if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cSelection))) { bHasSelectionProperty = sal_True; nSelectionPos = nPos; pValues[nPos].Value >>= aSelection; } else if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cCommandType))) pValues[nPos].Value >>= nCmdType; else if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cActiveConnection))) pValues[nPos].Value >>= xConnection; } if(!sDataSource.getLength() || !sDataTableOrQuery.getLength() || !xResSet.is()) { DBG_ERROR("PropertyValues missing or unset"); return; } uno::Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); uno::Reference xSource; uno::Reference xChild(xConnection, UNO_QUERY); if(xChild.is()) xSource = uno::Reference(xChild->getParent(), UNO_QUERY); if(!xSource.is()) xSource = SwNewDBMgr::GetDbtoolsClient().getDataSource(sDataSource, xMgr); uno::Reference< XColumnsSupplier > xColSupp( xResSet, UNO_QUERY ); SwDBData aDBData; aDBData.sDataSource = sDataSource; aDBData.sCommand = sDataTableOrQuery; aDBData.nCommandType = nCmdType; SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); DBG_ASSERT(pFact, "SwAbstractDialogFactory fail!"); AbstractSwInsertDBColAutoPilot* pDlg = pFact->CreateSwInsertDBColAutoPilot( rSh.GetView(), xSource, xColSupp, aDBData, DLG_AP_INSERT_DB_SEL ); DBG_ASSERT(pDlg, "Dialogdiet fail!"); if( RET_OK == pDlg->Execute() ) { rtl::OUString sDummy; if(!xConnection.is()) xConnection = xSource->getConnection(sDummy, sDummy); try { pDlg->DataToDoc( aSelection , xSource, xConnection, xResSet); } catch(Exception& ) { DBG_ERROR("exception caught"); } } delete pDlg; } /* -----------------------------30.08.2001 12:00------------------------------ ---------------------------------------------------------------------------*/ SwDbtoolsClient* SwNewDBMgr::pDbtoolsClient = NULL; SwDbtoolsClient& SwNewDBMgr::GetDbtoolsClient() { if ( !pDbtoolsClient ) pDbtoolsClient = new SwDbtoolsClient; return *pDbtoolsClient; } /* -----------------13.05.2003 15:34----------------- --------------------------------------------------*/ void SwNewDBMgr::RemoveDbtoolsClient() { delete pDbtoolsClient; pDbtoolsClient = 0; } /* -----------------------------20.08.2002 12:00------------------------------ ---------------------------------------------------------------------------*/ uno::Reference SwNewDBMgr::getDataSourceAsParent(const uno::Reference< XConnection>& _xConnection,const ::rtl::OUString& _sDataSourceName) { uno::Reference xSource; try { uno::Reference xChild(_xConnection, UNO_QUERY); if ( xChild.is() ) xSource = uno::Reference(xChild->getParent(), UNO_QUERY); if ( !xSource.is() ) xSource = SwNewDBMgr::GetDbtoolsClient().getDataSource(_sDataSourceName, ::comphelper::getProcessServiceFactory()); } catch(const Exception&) { DBG_ERROR("exception in getDataSourceAsParent caught"); } return xSource; } /* -----------------------------20.08.2002 12:00------------------------------ ---------------------------------------------------------------------------*/ uno::Reference SwNewDBMgr::createCursor(const ::rtl::OUString& _sDataSourceName, const ::rtl::OUString& _sCommand, sal_Int32 _nCommandType, const uno::Reference& _xConnection ) { uno::Reference xResultSet; try { uno::Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() ); if( xMgr.is() ) { uno::Reference xInstance = xMgr->createInstance( C2U( "com.sun.star.sdb.RowSet" )); uno::Reference xRowSetPropSet(xInstance, UNO_QUERY); if(xRowSetPropSet.is()) { xRowSetPropSet->setPropertyValue(C2U("DataSourceName"), makeAny(_sDataSourceName)); xRowSetPropSet->setPropertyValue(C2U("ActiveConnection"), makeAny(_xConnection)); xRowSetPropSet->setPropertyValue(C2U("Command"), makeAny(_sCommand)); xRowSetPropSet->setPropertyValue(C2U("CommandType"), makeAny(_nCommandType)); uno::Reference< XCompletedExecution > xRowSet(xInstance, UNO_QUERY); if ( xRowSet.is() ) { uno::Reference< XInteractionHandler > xHandler(xMgr->createInstance(C2U("com.sun.star.task.InteractionHandler")), UNO_QUERY); xRowSet->executeWithCompletion(xHandler); } xResultSet = uno::Reference(xRowSet, UNO_QUERY); } } } catch(const Exception&) { DBG_ASSERT(0,"Caught exception while creating a new RowSet!"); } return xResultSet; } /*-- 13.05.2004 16:14:15--------------------------------------------------- merge all data into one resulting document and return the number of merged documents -----------------------------------------------------------------------*/ sal_Int32 SwNewDBMgr::MergeDocuments( SwMailMergeConfigItem& rMMConfig, SwView& rSourceView ) { // check the availability of all data in the config item uno::Reference< XResultSet> xResultSet = rMMConfig.GetResultSet(); if(!xResultSet.is()) return false; bInMerge = sal_True; sal_Int32 nRet = 0; pImpl->pMergeData = new SwDSParam( rMMConfig.GetCurrentDBData(), xResultSet, rMMConfig.GetSelection()); try{ //set to start position if(pImpl->pMergeData->aSelection.getLength()) { sal_Int32 nPos = 0; pImpl->pMergeData->aSelection.getConstArray()[ pImpl->pMergeData->nSelectionIndex++ ] >>= nPos; pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->absolute( nPos ); pImpl->pMergeData->CheckEndOfDB(); if(pImpl->pMergeData->nSelectionIndex >= pImpl->pMergeData->aSelection.getLength()) pImpl->pMergeData->bEndOfDB = sal_True; } else { pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->first(); pImpl->pMergeData->CheckEndOfDB(); } } catch(Exception&) { pImpl->pMergeData->bEndOfDB = sal_True; pImpl->pMergeData->CheckEndOfDB(); DBG_ERROR("exception in MergeNew()"); } //bCancel is set from the PrintMonitor bCancel = sal_False; CreateMonitor aMonitorDlg(&rSourceView.GetEditWin()); aMonitorDlg.SetCancelHdl(LINK(this, SwNewDBMgr, PrtCancelHdl)); if (!IsMergeSilent()) { aMonitorDlg.Show(); aMonitorDlg.Invalidate(); aMonitorDlg.Update(); // the print monitor needs some time to act for( sal_uInt16 i = 0; i < 25; i++) Application::Reschedule(); } SwWrtShell& rSourceShell = rSourceView.GetWrtShell(); sal_Bool bSynchronizedDoc = rSourceShell.IsLabelDoc() && rSourceShell.GetSectionFmtCount() > 1; //save the settings of the first rSourceShell.SttEndDoc(sal_True); sal_uInt16 nStartingPageNo = rSourceShell.GetVirtPageNum(); String sModifiedStartingPageDesc; String sStartingPageDesc = sModifiedStartingPageDesc = rSourceShell.GetPageDesc( rSourceShell.GetCurPageDesc()).GetName(); try { // create a target docshell to put the merged document into SfxObjectShellRef xTargetDocShell( new SwDocShell( SFX_CREATE_MODE_STANDARD ) ); xTargetDocShell->DoInitNew( 0 ); SfxViewFrame* pTargetFrame = SfxViewFrame::LoadHiddenDocument( *xTargetDocShell, 0 ); //the created window has to be located at the same position as the source window Window& rTargetWindow = pTargetFrame->GetFrame().GetWindow(); Window& rSourceWindow = rSourceView.GetViewFrame()->GetFrame().GetWindow(); rTargetWindow.SetPosPixel(rSourceWindow.GetPosPixel()); // pTargetFrame->GetFrame().Appear(); SwView* pTargetView = static_cast( pTargetFrame->GetViewShell() ); rMMConfig.SetTargetView(pTargetView); //initiate SelectShell() to create sub shells pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() ); SwWrtShell* pTargetShell = pTargetView->GetWrtShellPtr(); // #i63806# const SwPageDesc* pSourcePageDesc = rSourceShell.FindPageDescByName( sStartingPageDesc ); const SwFrmFmt& rMaster = pSourcePageDesc->GetMaster(); bool bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive() || rMaster.GetFooter().IsActive(); // #122799# copy compatibility options lcl_CopyCompatibilityOptions( rSourceShell, *pTargetShell); // #72821# copy dynamic defaults lcl_CopyDynamicDefaults( *rSourceShell.GetDoc(), *pTargetShell->GetDoc() ); long nStartRow, nEndRow; sal_uLong nDocNo = 1; sal_Int32 nDocCount = 0; if( !IsMergeSilent() && lcl_getCountFromResultSet( nDocCount, pImpl->pMergeData->xResultSet ) ) aMonitorDlg.SetTotalCount( nDocCount ); do { nStartRow = pImpl->pMergeData->xResultSet->getRow(); if (!IsMergeSilent()) { aMonitorDlg.SetCurrentPosition( nDocNo ); aMonitorDlg.Invalidate(); aMonitorDlg.Update(); // the print monitor needs some time to act for( sal_uInt16 i = 0; i < 25; i++) Application::Reschedule(); } // copy the source document // the copy will be closed later, but it is more safe to use SfxObjectShellLock here SfxObjectShellLock xWorkDocSh; if(nDocNo == 1 ) { uno::Reference< util::XCloneable > xClone( rSourceView.GetDocShell()->GetModel(), uno::UNO_QUERY); uno::Reference< lang::XUnoTunnel > xWorkDocShell( xClone->createClone(), uno::UNO_QUERY); SwXTextDocument* pWorkModel = reinterpret_cast(xWorkDocShell->getSomething(SwXTextDocument::getUnoTunnelId())); xWorkDocSh = pWorkModel->GetDocShell(); } else { xWorkDocSh = rSourceView.GetDocShell()->GetDoc()->CreateCopy(true); } //create a ViewFrame SwView* pWorkView = static_cast< SwView* >( SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 )->GetViewShell() ); SwWrtShell& rWorkShell = pWorkView->GetWrtShell(); pWorkView->AttrChangedNotify( &rWorkShell );//Damit SelectShell gerufen wird. // merge the data SwDoc* pWorkDoc = rWorkShell.GetDoc(); SwNewDBMgr* pWorkDBMgr = pWorkDoc->GetNewDBMgr(); pWorkDoc->SetNewDBMgr( this ); pWorkDoc->EmbedAllLinks(); SwUndoId nLastUndoId(UNDO_EMPTY); if (rWorkShell.GetLastUndoInfo(0, & nLastUndoId)) { if (UNDO_UI_DELETE_INVISIBLECNTNT == nLastUndoId) { rWorkShell.Undo(); } } // #i69485# lock fields to prevent access to the result set while calculating layout rWorkShell.LockExpFlds(); // create a layout rWorkShell.CalcLayout(); rWorkShell.UnlockExpFlds(); SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), rWorkShell.GetView().GetViewFrame()->GetObjectShell())); rWorkShell.ViewShell::UpdateFlds(); SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), rWorkShell.GetView().GetViewFrame()->GetObjectShell())); // strip invisible content and convert fields to text rWorkShell.RemoveInvisibleContent(); rWorkShell.ConvertFieldsToText(); rWorkShell.SetNumberingRestart(); if( bSynchronizedDoc ) { lcl_RemoveSectionLinks( rWorkShell ); } // insert the document into the target document rWorkShell.SttEndDoc(sal_False); rWorkShell.SttEndDoc(sal_True); rWorkShell.SelAll(); pTargetShell->SttEndDoc(sal_False); //#i63806# put the styles to the target document //if the source uses headers or footers each new copy need to copy a new page styles if(bPageStylesWithHeaderFooter) { //create a new pagestyle //copy the pagedesc from the current document to the new document and change the name of the to-be-applied style SwDoc* pTargetDoc = pTargetShell->GetDoc(); String sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo ); pTargetShell->GetDoc()->MakePageDesc( sNewPageDescName ); SwPageDesc* pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName ); const SwPageDesc* pWorkPageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc ); if(pWorkPageDesc && pTargetPageDesc) { pTargetDoc->CopyPageDesc( *pWorkPageDesc, *pTargetPageDesc, sal_False ); sModifiedStartingPageDesc = sNewPageDescName; lcl_CopyFollowPageDesc( *pTargetShell, *pWorkPageDesc, *pTargetPageDesc, nDocNo ); } } if(nDocNo == 1 || bPageStylesWithHeaderFooter) { pTargetView->GetDocShell()->_LoadStyles( *rSourceView.GetDocShell(), sal_True ); } if(nDocNo > 1) { pTargetShell->InsertPageBreak( &sModifiedStartingPageDesc, nStartingPageNo ); } else { pTargetShell->SetPageStyle(sModifiedStartingPageDesc); } sal_uInt16 nPageCountBefore = pTargetShell->GetPageCnt(); DBG_ASSERT(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended"); //#i51359# add a second paragraph in case there's only one { SwNodeIndex aIdx( pWorkDoc->GetNodes().GetEndOfExtras(), 2 ); SwPosition aTestPos( aIdx ); SwCursor aTestCrsr(aTestPos,0,false); if(!aTestCrsr.MovePara(fnParaNext, fnParaStart)) { //append a paragraph pWorkDoc->AppendTxtNode( aTestPos ); } } pTargetShell->Paste( rWorkShell.GetDoc(), sal_True ); //convert fields in page styles (header/footer - has to be done after the first document has been pasted if(1 == nDocNo) { pTargetShell->CalcLayout(); pTargetShell->ConvertFieldsToText(); } //add the document info to the config item SwDocMergeInfo aMergeInfo; aMergeInfo.nStartPageInTarget = nPageCountBefore; //#i72820# calculate layout to be able to find the correct page index pTargetShell->CalcLayout(); aMergeInfo.nEndPageInTarget = pTargetShell->GetPageCnt(); aMergeInfo.nDBRow = nStartRow; rMMConfig.AddMergedDocument( aMergeInfo ); ++nRet; // the print monitor needs some time to act for( sal_uInt16 i = 0; i < 25; i++) Application::Reschedule(); //restore the ole DBMgr pWorkDoc->SetNewDBMgr( pWorkDBMgr ); //now the temporary document should be closed SfxObjectShellRef xDocSh(pWorkView->GetDocShell()); xDocSh->DoClose(); nEndRow = pImpl->pMergeData->xResultSet->getRow(); ++nDocNo; } while( !bCancel && (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord())); //deselect all, go out of the frame and go to the beginning of the document Point aPt(LONG_MIN, LONG_MIN); pTargetShell->SelectObj(aPt, SW_LEAVE_FRAME); if (pTargetShell->IsSelFrmMode()) { pTargetShell->UnSelectFrm(); pTargetShell->LeaveSelFrmMode(); } pTargetShell->EnterStdMode(); pTargetShell->SttDoc(); // } catch( Exception& rEx) { (void)rEx; DBG_ERROR("exception caught in SwNewDBMgr::MergeDocuments"); } DELETEZ(pImpl->pMergeData); bInMerge = sal_False; return nRet; } /* -----------------09.12.2002 12:38----------------- * * --------------------------------------------------*/ SwConnectionDisposedListener_Impl::SwConnectionDisposedListener_Impl(SwNewDBMgr& rMgr) : rDBMgr(rMgr) {}; /* -----------------09.12.2002 12:39----------------- * * --------------------------------------------------*/ SwConnectionDisposedListener_Impl::~SwConnectionDisposedListener_Impl() {}; /* -----------------09.12.2002 12:39----------------- * * --------------------------------------------------*/ void SwConnectionDisposedListener_Impl::disposing( const EventObject& rSource ) throw (RuntimeException) { ::vos::OGuard aGuard(Application::GetSolarMutex()); uno::Reference xSource(rSource.Source, UNO_QUERY); for(sal_uInt16 nPos = rDBMgr.aDataSourceParams.Count(); nPos; nPos--) { SwDSParam* pParam = rDBMgr.aDataSourceParams[nPos - 1]; if(pParam->xConnection.is() && (xSource == pParam->xConnection)) { rDBMgr.aDataSourceParams.DeleteAndDestroy(nPos - 1); } } }