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 <mike.kaganski@collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190077
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
Laurent Balland
2025-11-16 16:05:34 +01:00
committed by Mike Kaganski
co-authored by Mike Kaganski
parent efd69fbd84
commit ba49c9249f
15 changed files with 97 additions and 44 deletions
@@ -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>
+2 -1
View File
@@ -180,8 +180,9 @@ enum class SotClipboardFormatId : sal_uInt32
PDF = 147,
SVG = 148,
MARKDOWN = 149,
BIFF_12 = 150,
// the point at which we start allocating "runtime" format IDs
USER_END = MARKDOWN
USER_END = BIFF_12
};
/** Make it easier to iterate over format IDs */
+1
View File
@@ -71,6 +71,7 @@
#define STR_FORMAT_ID_MARKDOWN NC_("STR_FORMAT_ID_MARKDOWN", "Markdown")
#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)")
+1 -1
View File
@@ -2917,7 +2917,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 );
}
+5
View File
@@ -2966,6 +2966,11 @@ 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, const std::shared_ptr<ScDocument>& pDoc ) :
SfxObjectShell( i_nSfxCreationFlags ),
m_pDocument ( pDoc ? pDoc : std::make_shared<ScDocument>( SCDOCMODE_DOCUMENT, this )),
+1
View File
@@ -171,6 +171,7 @@ private:
public:
explicit ScDocShell( const ScDocShell& rDocShell ) = delete;
SC_DLLPUBLIC explicit ScDocShell( const SfxModelFlags i_nSfxCreationFlags = SfxModelFlags::EMBEDDED_OBJECT, const std::shared_ptr<ScDocument>& pDoc = {} );
explicit ScDocShell(const SfxModelFlags i_nSfxCreationFlags, ScDocumentMode);
virtual ~ScDocShell() override;
SC_DLLPUBLIC virtual SfxUndoManager* GetUndoManager() override;
+3
View File
@@ -418,6 +418,9 @@ private:
SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount );
bool CheckSheetViewProtection(sc::Operation eOperation);
void PasteFromExcelClip(ScDocument& rClipDoc, SCTAB nSrcTab, SCCOL nPosX, SCROW nPosY,
const Point* pLogicPos, bool bAllowDialogs);
};
extern bool bPasteIsMove;
+1
View File
@@ -492,6 +492,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 );
}
+2
View File
@@ -4466,6 +4466,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 ) )
+8 -2
View File
@@ -517,6 +517,7 @@ void ScViewFunc::PasteFromSystem(bool useSavedPrefs)
TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
{
SotClipboardFormatId nBiff12= SotExchange::RegisterFormatName(u"Biff12"_ustr);
SotClipboardFormatId nBiff8 = SotExchange::RegisterFormatName(u"Biff8"_ustr);
SotClipboardFormatId nBiff5 = SotExchange::RegisterFormatName(u"Biff5"_ustr);
@@ -602,7 +603,9 @@ void ScViewFunc::PasteFromSystem(bool useSavedPrefs)
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);
@@ -656,6 +659,7 @@ void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTran
else
{
TransferableDataHelper aDataHelper( rxTransferable );
SotClipboardFormatId nBiff12 = SotExchange::RegisterFormatName(u"Biff12"_ustr);
SotClipboardFormatId nBiff8 = SotExchange::RegisterFormatName(u"Biff8"_ustr);
SotClipboardFormatId nBiff5 = SotExchange::RegisterFormatName(u"Biff5"_ustr);
SotClipboardFormatId nFormatId = SotClipboardFormatId::NONE;
@@ -688,7 +692,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;
+67 -39
View File
@@ -39,6 +39,7 @@
#include <svx/GenericDropDownFieldDialog.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>
@@ -83,6 +84,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, bool useSavedPrefs )
@@ -290,6 +333,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, SCDOCMODE_CLIP));
SCTAB nSrcTab = 0;
pClipShell->GetDocument().ResetClip(&rDoc, 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
@@ -306,45 +372,7 @@ bool ScViewFunc::PasteDataFormat( SotClipboardFormatId nFormatId,
ErrCode eErr = ScFormatFilter::Get().ScImportExcel( aMed, &aInsDoc, EIF_AUTO );
if ( eErr == ERRCODE_NONE )
{
ScRange aSource;
const ScExtDocOptions* pExtOpt = aInsDoc.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 ( aInsDoc.GetDataStart( nSrcTab, nFirstCol, nFirstRow ) )
aInsDoc.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();
}
aInsDoc.SetClipArea( aSource );
PasteFromClip( InsertDeleteFlags::ALL, &aInsDoc,
ScPasteFunc::NONE, false, false, false, INS_NONE, InsertDeleteFlags::NONE,
bAllowDialogs );
PasteFromExcelClip(aInsDoc, nSrcTab, nPosX, nPosY, pLogicPos, bAllowDialogs);
bRet = true;
}
}
+1
View File
@@ -198,6 +198,7 @@ const DataFlavor* FormatArray_Impl()
/*147 PDF*/ { u"application/pdf"_ustr, u"PDF Document"_ustr, cppu::UnoType<Sequence<sal_Int8>>::get() },
/*148 SVG*/ { u"image/svg+xml;windows_formatname=\"image/svg+xml\""_ustr, u"SVG"_ustr, cppu::UnoType<Sequence<sal_Int8>>::get() },
/*149 MARKDOWN*/ { u"text/markdown"_ustr, u"Markdown"_ustr, cppu::UnoType<Sequence<sal_Int8>>::get() },
/*150 BIFF_12*/ { u"application/x-openoffice-biff-12;windows_formatname=\"Biff12\""_ustr, u"Biff12"_ustr, cppu::UnoType<Sequence<sal_Int8>>::get() },
};
assert(std::size(aInstance) == size_t(SotClipboardFormatId::USER_END) + 1);
return &aInstance[0];
+2
View File
@@ -1017,6 +1017,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 },
};
SotAction_Impl const aEXCHG_DEST_SCDOC_FREE_AREA_Copy[] =
{
@@ -1045,6 +1046,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 },
};
SotAction_Impl const aEXCHG_DEST_SCDOC_FREE_AREA_Link[] =
{
+1
View File
@@ -208,6 +208,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 },
+1
View File
@@ -177,6 +177,7 @@ auto initTranslTable()
FormatEntry(xFactory, SotClipboardFormatId::BIFF_5),
FormatEntry(xFactory, SotClipboardFormatId::BIFF__5),
FormatEntry(xFactory, SotClipboardFormatId::BIFF_8),
FormatEntry(xFactory, SotClipboardFormatId::BIFF_12),
FormatEntry(xFactory, SotClipboardFormatId::SYLK_BIGCAPS),
FormatEntry(xFactory, SotClipboardFormatId::LINK),
FormatEntry(xFactory, SotClipboardFormatId::STARDRAW_TABBAR),