filter/source/config/fragments/types/MS_Excel_2007_Binary.xcu | 2 include/sot/formats.hxx | 3 include/svtools/strings.hrc | 1 sc/source/core/data/drwlayer.cxx | 2 sc/source/ui/docshell/docsh.cxx | 6 sc/source/ui/inc/docsh.hxx | 1 sc/source/ui/inc/viewfunc.hxx | 3 sc/source/ui/view/cellsh.cxx | 1 sc/source/ui/view/gridwin.cxx | 2 sc/source/ui/view/viewfun3.cxx | 10 sc/source/ui/view/viewfun5.cxx | 106 ++++++---- sot/source/base/exchange.cxx | 1 sot/source/base/formats.cxx | 2 svtools/source/dialogs/insdlg.cxx | 1 vcl/win/dtrans/ftransl.cxx | 2 15 files changed, 99 insertions(+), 44 deletions(-)
New commits: commit 04e2c1a2e9d3148bc1f652d6a50275352c5568b0 Author: Laurent Balland <[email protected]> AuthorDate: Fri Aug 22 17:59:30 2025 +0200 Commit: Thorsten Behrens <[email protected]> CommitDate: Sun Feb 22 19:32:19 2026 +0100 tdf#127675 Treat Biff12 when pasting Prior to Biff8, Biff12 is tested as format for pasting. The new format is read using SfxObjectShell::DoLoad. Since the import must be to an ScDocument in SCDOCMODE_CLIP mode, a new ctor was added for SfxObjectShell, that initializes the document with needed mode. The change in MS_Excel_2007_Binary.xcu enables GetFilter4ClipBoardId to return the correct filter. Since clipboard documents don't have a chart listener collection, we must not call SetChartListenerCollectionNeedsUpdate from SetChanged; otherwise, ScDocument::UpdateChartListenerCollection would crash. Change-Id: If57b1ffb9a2f8d0573cf77b9eb82f81aa4250b5e Co-authored-by: Mike Kaganski <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190077 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198703 Reviewed-by: Thorsten Behrens <[email protected]> Tested-by: allotropia jenkins <[email protected]> diff --git a/filter/source/config/fragments/types/MS_Excel_2007_Binary.xcu b/filter/source/config/fragments/types/MS_Excel_2007_Binary.xcu index 14a03a846288..525eac266c94 100644 --- a/filter/source/config/fragments/types/MS_Excel_2007_Binary.xcu +++ b/filter/source/config/fragments/types/MS_Excel_2007_Binary.xcu @@ -23,5 +23,5 @@ <prop oor:name="Preferred"><value>false</value></prop> <prop oor:name="PreferredFilter"><value>Calc MS Excel 2007 Binary</value></prop> <prop oor:name="UIName"><value xml:lang="en-US">Microsoft Excel 2007 Binary</value></prop> - <prop oor:name="ClipboardFormat"/> + <prop oor:name="ClipboardFormat"><value>Biff12</value></prop> </node> diff --git a/include/sot/formats.hxx b/include/sot/formats.hxx index 12727ffb34c9..64896266f1e4 100644 --- a/include/sot/formats.hxx +++ b/include/sot/formats.hxx @@ -175,8 +175,9 @@ enum class SotClipboardFormatId : sal_uInt32 RICHTEXT = 145, STRING_TSVC = 146, PDF = 147, + BIFF_12 = 148, // the point at which we start allocating "runtime" format IDs - USER_END = PDF + USER_END = BIFF_12 }; /** Make it easier to iterate over format IDs */ diff --git a/include/svtools/strings.hrc b/include/svtools/strings.hrc index 5b99e51605e3..e2b1bab26f22 100644 --- a/include/svtools/strings.hrc +++ b/include/svtools/strings.hrc @@ -71,6 +71,7 @@ #define STR_FORMAT_ID_HTML_SIMPLE NC_("STR_FORMAT_ID_HTML_SIMPLE", "Stripped HyperText Markup Language (Simple HTML)") #define STR_FORMAT_ID_BIFF_5 NC_("STR_FORMAT_ID_BIFF_5", "Microsoft Excel Binary Interchange Format 5.0/95 (Biff5)") #define STR_FORMAT_ID_BIFF_8 NC_("STR_FORMAT_ID_BIFF_8", "Microsoft Excel Binary Interchange Format 97/2000/XP/2003 (Biff8)") +#define STR_FORMAT_ID_BIFF_12 NC_("STR_FORMAT_ID_BIFF_12", "Microsoft Excel Binary Interchange Format 2007 (Biff12)") #define STR_FORMAT_ID_SYLK NC_("STR_FORMAT_ID_SYLK", "Sylk") #define STR_FORMAT_ID_LINK NC_("STR_FORMAT_ID_LINK", "Dynamic Data Exchange (DDE link)" ) #define STR_FORMAT_ID_DIF NC_("STR_FORMAT_ID_DIF", "Data Interchange Format (DIF)") diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx index 0bb4314309dc..ae9e3eeaaef3 100644 --- a/sc/source/core/data/drwlayer.cxx +++ b/sc/source/core/data/drwlayer.cxx @@ -2361,7 +2361,7 @@ void ScDrawLayer::SetGlobalDrawPersist(SfxObjectShell* pPersist) void ScDrawLayer::SetChanged( bool bFlg /* = true */ ) { - if ( bFlg && pDoc ) + if (bFlg && pDoc && pDoc->GetChartListenerCollection()) // clip documents don't have it pDoc->SetChartListenerCollectionNeedsUpdate( true ); FmFormModel::SetChanged( bFlg ); } diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 2203ca42725c..c0442bdd3cc5 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -2733,6 +2733,12 @@ std::unique_ptr<ScDocFunc> ScDocShell::CreateDocFunc() return std::make_unique<ScDocFuncDirect>( *this ); } +/*ScDocShell::ScDocShell(const SfxModelFlags i_nSfxCreationFlags, ScDocumentMode docMode) + : ScDocShell(i_nSfxCreationFlags, std::make_shared<ScDocument>(docMode, this)) +{ +} +*/ + ScDocShell::ScDocShell( const SfxModelFlags i_nSfxCreationFlags ) : SfxObjectShell( i_nSfxCreationFlags ), m_aDocument ( SCDOCMODE_DOCUMENT, this ), diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx index a519f4c87d04..5851ed9449ec 100644 --- a/sc/source/ui/inc/docsh.hxx +++ b/sc/source/ui/inc/docsh.hxx @@ -172,6 +172,7 @@ private: public: explicit ScDocShell( const ScDocShell& rDocShell ) = delete; explicit ScDocShell( const SfxModelFlags i_nSfxCreationFlags = SfxModelFlags::EMBEDDED_OBJECT ); +// explicit ScDocShell(const SfxModelFlags i_nSfxCreationFlags, ScDocumentMode); virtual ~ScDocShell() override; virtual SfxUndoManager* diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx index fd1e05fa1a67..bb481c20e091 100644 --- a/sc/source/ui/inc/viewfunc.hxx +++ b/sc/source/ui/inc/viewfunc.hxx @@ -371,6 +371,9 @@ private: void MarkAndJumpToRanges(const ScRangeList& rRanges); void CopyAutoSpellData( FillDir eDir, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount ); + + void PasteFromExcelClip(ScDocument& rClipDoc, SCTAB nSrcTab, SCCOL nPosX, SCROW nPosY, + const Point* pLogicPos, bool bAllowDialogs); }; extern bool bPasteIsDrop; diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx index 6b1fc8cf7ef0..42af56e85df1 100644 --- a/sc/source/ui/view/cellsh.cxx +++ b/sc/source/ui/view/cellsh.cxx @@ -467,6 +467,7 @@ void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFormatItem& rFormats lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::RICHTEXT ); lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::HTML ); lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::HTML_SIMPLE ); + lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::BIFF_12 ); lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::BIFF_8 ); lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::BIFF_5 ); } diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 81d4509d2808..12083be14e99 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -3849,6 +3849,8 @@ static SotClipboardFormatId lcl_GetDropFormatId( const uno::Reference<datatransf nFormatId = SotClipboardFormatId::SBA_DATAEXCHANGE; else if ( aDataHelper.HasFormat( SotClipboardFormatId::SBA_FIELDDATAEXCHANGE ) ) nFormatId = SotClipboardFormatId::SBA_FIELDDATAEXCHANGE; + else if ( aDataHelper.HasFormat( SotClipboardFormatId::BIFF_12 ) ) + nFormatId = SotClipboardFormatId::BIFF_12; else if ( aDataHelper.HasFormat( SotClipboardFormatId::BIFF_8 ) ) nFormatId = SotClipboardFormatId::BIFF_8; else if ( aDataHelper.HasFormat( SotClipboardFormatId::BIFF_5 ) ) diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx index 7a39f5037fa2..b3903f496e28 100644 --- a/sc/source/ui/view/viewfun3.cxx +++ b/sc/source/ui/view/viewfun3.cxx @@ -504,6 +504,7 @@ void ScViewFunc::PasteFromSystem() TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) ); { + SotClipboardFormatId nBiff12 = SotExchange::RegisterFormatName("Biff12"); SotClipboardFormatId nBiff8 = SotExchange::RegisterFormatName("Biff8"); SotClipboardFormatId nBiff5 = SotExchange::RegisterFormatName("Biff5"); @@ -589,7 +590,9 @@ void ScViewFunc::PasteFromSystem() else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE )) PasteFromSystem( SotClipboardFormatId::EMBEDDED_OBJ_OLE ); // SotClipboardFormatId::PRIVATE no longer here (can't work if pOwnClip is NULL) - else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats + else if (aDataHelper.HasFormat(nBiff12)) // before xxx_OLE formats + PasteFromSystem(nBiff12); + else if (aDataHelper.HasFormat(nBiff8)) PasteFromSystem(nBiff8); else if (aDataHelper.HasFormat(nBiff5)) PasteFromSystem(nBiff5); @@ -657,6 +660,7 @@ void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTran else { TransferableDataHelper aDataHelper( rxTransferable ); + SotClipboardFormatId nBiff12 = SotExchange::RegisterFormatName("Biff12"); SotClipboardFormatId nBiff8 = SotExchange::RegisterFormatName("Biff8"); SotClipboardFormatId nBiff5 = SotExchange::RegisterFormatName("Biff5"); SotClipboardFormatId nFormatId = SotClipboardFormatId::NONE; @@ -689,7 +693,9 @@ void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTran else if (aDataHelper.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE )) nFormatId = SotClipboardFormatId::EMBEDDED_OBJ_OLE; // SotClipboardFormatId::PRIVATE no longer here (can't work if pOwnClip is NULL) - else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats + else if (aDataHelper.HasFormat(nBiff12)) // before xxx_OLE formats + nFormatId = nBiff12; + else if (aDataHelper.HasFormat(nBiff8)) nFormatId = nBiff8; else if (aDataHelper.HasFormat(nBiff5)) nFormatId = nBiff5; diff --git a/sc/source/ui/view/viewfun5.cxx b/sc/source/ui/view/viewfun5.cxx index 0e61a2a8a072..251c945b06ad 100644 --- a/sc/source/ui/view/viewfun5.cxx +++ b/sc/source/ui/view/viewfun5.cxx @@ -33,6 +33,7 @@ #include <svx/svdpage.hxx> #include <sfx2/dispatch.hxx> #include <sfx2/docfile.hxx> +#include <sfx2/fcontnr.hxx> #include <comphelper/classids.hxx> #include <sot/formats.hxx> #include <sot/filelist.hxx> @@ -72,6 +73,48 @@ using namespace com::sun::star; +void ScViewFunc::PasteFromExcelClip(ScDocument& rClipDoc, SCTAB nSrcTab, SCCOL nPosX, SCROW nPosY, + const Point* pLogicPos, bool bAllowDialogs) +{ + ScRange aSource; + const ScExtDocOptions* pExtOpt = rClipDoc.GetExtDocOptions(); + const ScExtTabSettings* pTabSett = pExtOpt ? pExtOpt->GetTabSettings(nSrcTab) : nullptr; + if (pTabSett && pTabSett->maUsedArea.IsValid()) + { + aSource = pTabSett->maUsedArea; + // ensure correct sheet indexes + aSource.aStart.SetTab(nSrcTab); + aSource.aEnd.SetTab(nSrcTab); + // don't use selection area: if cursor is moved in Excel after Copy, selection + // represents the new cursor position and not the copied area + } + else + { + // Biff12 goes here + SCCOL nFirstCol, nLastCol; + SCROW nFirstRow, nLastRow; + if (rClipDoc.GetDataStart(nSrcTab, nFirstCol, nFirstRow)) + rClipDoc.GetCellArea(nSrcTab, nLastCol, nLastRow); + else + { + nFirstCol = nLastCol = 0; + nFirstRow = nLastRow = 0; + } + aSource = ScRange(nFirstCol, nFirstRow, nSrcTab, nLastCol, nLastRow, nSrcTab); + } + + if (pLogicPos) + { + // position specified (Drag&Drop) - change selection + MoveCursorAbs(nPosX, nPosY, SC_FOLLOW_NONE, false, false); + Unmark(); + } + + rClipDoc.SetClipArea(aSource); + PasteFromClip(InsertDeleteFlags::ALL, &rClipDoc, ScPasteFunc::NONE, false, + false, false, INS_NONE, InsertDeleteFlags::NONE, bAllowDialogs); +} + bool ScViewFunc::PasteDataFormat( SotClipboardFormatId nFormatId, const uno::Reference<datatransfer::XTransferable>& rxTransferable, SCCOL nPosX, SCROW nPosY, const Point* pLogicPos, bool bLink, bool bAllowDialogs ) @@ -551,6 +594,29 @@ bool ScViewFunc::PasteDataFormat( SotClipboardFormatId nFormatId, bRet = true; } } + else if (nFormatId == SotClipboardFormatId::BIFF_12) + { + if (auto xStm = aDataHelper.GetInputStream(nFormatId, {})) + { + SfxFilterMatcher aMatcher(ScDocShell::Factory().GetFilterContainer()->GetName()); + if (auto pFilter = aMatcher.GetFilter4ClipBoardId(SotClipboardFormatId::BIFF_12)) + { + ScDocShellRef pClipShell(new ScDocShell(SfxModelFlags::NONE)); + SCTAB nSrcTab = 0; + pClipShell->GetDocument().ResetClip(pDoc, nSrcTab); + SfxMedium aMed; + aMed.GetItemSet()->Put(SfxUnoAnyItem(SID_INPUTSTREAM, uno::Any(xStm))); + aMed.SetFilter(pFilter); + + if (pClipShell->DoLoad(&aMed)) + { + PasteFromExcelClip(pClipShell->GetDocument(), nSrcTab, nPosX, nPosY, pLogicPos, + bAllowDialogs); + bRet = true; + } + } + } + } else if ( (nFormatId == SotClipboardFormatId::BIFF_5) || (nFormatId == SotClipboardFormatId::BIFF_8) ) { // do excel import into a clipboard document @@ -567,45 +633,7 @@ bool ScViewFunc::PasteDataFormat( SotClipboardFormatId nFormatId, ErrCode eErr = ScFormatFilter::Get().ScImportExcel( aMed, pInsDoc.get(), EIF_AUTO ); if ( eErr == ERRCODE_NONE ) { - ScRange aSource; - const ScExtDocOptions* pExtOpt = pInsDoc->GetExtDocOptions(); - const ScExtTabSettings* pTabSett = pExtOpt ? pExtOpt->GetTabSettings( nSrcTab ) : nullptr; - if( pTabSett && pTabSett->maUsedArea.IsValid() ) - { - aSource = pTabSett->maUsedArea; - // ensure correct sheet indexes - aSource.aStart.SetTab( nSrcTab ); - aSource.aEnd.SetTab( nSrcTab ); -// don't use selection area: if cursor is moved in Excel after Copy, selection -// represents the new cursor position and not the copied area - } - else - { - OSL_FAIL("no dimension"); //! possible? - SCCOL nFirstCol, nLastCol; - SCROW nFirstRow, nLastRow; - if ( pInsDoc->GetDataStart( nSrcTab, nFirstCol, nFirstRow ) ) - pInsDoc->GetCellArea( nSrcTab, nLastCol, nLastRow ); - else - { - nFirstCol = nLastCol = 0; - nFirstRow = nLastRow = 0; - } - aSource = ScRange( nFirstCol, nFirstRow, nSrcTab, - nLastCol, nLastRow, nSrcTab ); - } - - if ( pLogicPos ) - { - // position specified (Drag&Drop) - change selection - MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, false, false ); - Unmark(); - } - - pInsDoc->SetClipArea( aSource ); - PasteFromClip( InsertDeleteFlags::ALL, pInsDoc.get(), - ScPasteFunc::NONE, false, false, false, INS_NONE, InsertDeleteFlags::NONE, - bAllowDialogs ); + PasteFromExcelClip(*pInsDoc, nSrcTab, nPosX, nPosY, pLogicPos, bAllowDialogs); bRet = true; } } diff --git a/sot/source/base/exchange.cxx b/sot/source/base/exchange.cxx index da90eef263d7..493049cd3665 100644 --- a/sot/source/base/exchange.cxx +++ b/sot/source/base/exchange.cxx @@ -203,6 +203,7 @@ namespace /*145 SotClipboardFormatId::RICHTEXT*/ { "text/richtext", "Richtext Format", &cppu::UnoType<Sequence<sal_Int8>>::get() }, /*146 SotClipboardFormatId::STRING_TSVC*/ { "application/x-libreoffice-tsvc", "Text TSV-Calc", &cppu::UnoType<OUString>::get() }, /*147 SotClipboardFormatId::PDF*/ { "application/pdf", "PDF Document", &cppu::UnoType<Sequence<sal_Int8>>::get() }, + /*148 SotClipboardFormatId::BIFF_12*/ { "application/x-openoffice-biff-12;windows_formatname=\"Biff12\"", "Biff12", &cppu::UnoType<Sequence<sal_Int8>>::get() }, }; return &aInstance[0]; } diff --git a/sot/source/base/formats.cxx b/sot/source/base/formats.cxx index 51c6b157496f..ce50ddc807a6 100644 --- a/sot/source/base/formats.cxx +++ b/sot/source/base/formats.cxx @@ -1076,6 +1076,7 @@ SotAction_Impl const aEXCHG_DEST_SCDOC_FREE_AREA_Move[] = { SotClipboardFormatId::LINK, EXCHG_OUT_ACTION_INSERT_DDE, SotExchangeActionFlags::InsertTargetUrl, 0 }, { SotClipboardFormatId::SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP, SotExchangeActionFlags::InsertTargetUrl, 0 }, { SotClipboardFormatId::BIFF_8, EXCHG_IN_ACTION_MOVE, SotExchangeActionFlags::InsertTargetUrl, 0 }, + { SotClipboardFormatId::BIFF_12, EXCHG_IN_ACTION_MOVE, SotExchangeActionFlags::InsertTargetUrl, 0 }, { static_cast<SotClipboardFormatId>(0xffff), 0 } }; SotAction_Impl const aEXCHG_DEST_SCDOC_FREE_AREA_Copy[] = @@ -1105,6 +1106,7 @@ SotAction_Impl const aEXCHG_DEST_SCDOC_FREE_AREA_Copy[] = { SotClipboardFormatId::LINK, EXCHG_OUT_ACTION_INSERT_DDE, SotExchangeActionFlags::InsertTargetUrl, 0 }, { SotClipboardFormatId::SVIM, EXCHG_OUT_ACTION_INSERT_IMAGEMAP, SotExchangeActionFlags::InsertTargetUrl, 0 }, { SotClipboardFormatId::BIFF_8, EXCHG_IN_ACTION_COPY, SotExchangeActionFlags::InsertTargetUrl, 0 }, + { SotClipboardFormatId::BIFF_12, EXCHG_IN_ACTION_COPY, SotExchangeActionFlags::InsertTargetUrl, 0 }, { static_cast<SotClipboardFormatId>(0xffff), 0 } }; SotAction_Impl const aEXCHG_DEST_SCDOC_FREE_AREA_Link[] = diff --git a/svtools/source/dialogs/insdlg.cxx b/svtools/source/dialogs/insdlg.cxx index 2ae9eb66dc9a..8da514d4e710 100644 --- a/svtools/source/dialogs/insdlg.cxx +++ b/svtools/source/dialogs/insdlg.cxx @@ -226,6 +226,7 @@ OUString SvPasteObjectHelper::GetSotFormatUIName( SotClipboardFormatId nId ) { SotClipboardFormatId::HTML_SIMPLE, STR_FORMAT_ID_HTML_SIMPLE }, { SotClipboardFormatId::BIFF_5, STR_FORMAT_ID_BIFF_5 }, { SotClipboardFormatId::BIFF_8, STR_FORMAT_ID_BIFF_8 }, + { SotClipboardFormatId::BIFF_12, STR_FORMAT_ID_BIFF_12 }, { SotClipboardFormatId::SYLK, STR_FORMAT_ID_SYLK }, { SotClipboardFormatId::LINK, STR_FORMAT_ID_LINK }, { SotClipboardFormatId::DIF, STR_FORMAT_ID_DIF }, diff --git a/vcl/win/dtrans/ftransl.cxx b/vcl/win/dtrans/ftransl.cxx index e2a6581abfec..74dbf5ed0095 100644 --- a/vcl/win/dtrans/ftransl.cxx +++ b/vcl/win/dtrans/ftransl.cxx @@ -216,6 +216,8 @@ static const std::vector< FormatEntry > g_TranslTable { FormatEntry("application/x-openoffice-biff-5;windows_formatname=\"Biff 5\"", "Biff 5", nullptr, CF_INVALID, CPPUTYPE_DEFAULT), //SotClipboardFormatId::BIFF_8 FormatEntry("application/x-openoffice-biff-8;windows_formatname=\"Biff8\"", "Biff8", nullptr, CF_INVALID, CPPUTYPE_DEFAULT), + //SotClipboardFormatId::BIFF_12 + FormatEntry("application/x-openoffice-biff-12;windows_formatname=\"Biff12\"", "Biff12", nullptr, CF_INVALID, CPPUTYPE_DEFAULT), //SotClipboardFormatId::SYLK_BIGCAPS FormatEntry("application/x-openoffice-sylk-bigcaps;windows_formatname=\"SYLK\"", "SYLK", nullptr, CF_INVALID, CPPUTYPE_DEFAULT), //SotClipboardFormatId::LINK
