filter/source/msfilter/eschesdo.cxx | 23 +- include/oox/token/relationship.hxx | 1 oox/source/token/relationship.inc | 1 sc/source/filter/excel/excdoc.cxx | 7 sc/source/filter/excel/xeescher.cxx | 351 +++++++++++++++++++++++++++++++++--- sc/source/filter/inc/xcl97rec.hxx | 2 sc/source/filter/inc/xeescher.hxx | 17 + sc/source/filter/xcl97/xcl97rec.cxx | 58 +++++ 8 files changed, 419 insertions(+), 41 deletions(-)
New commits: commit fd238380ae7820f12ac1f7c52d0f7180a93f3ba3 Author: Serge Krot <serge.k...@cib.de> AuthorDate: Wed May 13 22:52:52 2020 +0200 Commit: Thorsten Behrens <thorsten.behr...@cib.de> CommitDate: Tue May 26 00:20:54 2020 +0200 tdf#106181 XLSX export: output form controls Prepared general algorithm to ouput form controls into XLSX. For now only CHECKBOX is supported with a possibility to link withem to any worksheet/cell. Change-Id: Ide8739d81ffb755aeae074c4ebecf24251383e34 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94161 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> diff --git a/filter/source/msfilter/eschesdo.cxx b/filter/source/msfilter/eschesdo.cxx index 22f47daa15af..efe3c908b6b4 100644 --- a/filter/source/msfilter/eschesdo.cxx +++ b/filter/source/msfilter/eschesdo.cxx @@ -401,11 +401,16 @@ sal_uInt32 ImplEESdrWriter::ImplWriteShape( ImplEESdrObject& rObj, const Reference< XPropertySet > xPropSet = rObj.mXPropSet; const Reference<XPropertySetInfo> xPropInfo = xPropSet.is() ? xPropSet->getPropertySetInfo() : Reference<XPropertySetInfo>(); // This code is expected to be called only for DOCX format. - if (xPropInfo.is() && xPropInfo->hasPropertyByName("AnchorType") && bOOxmlExport) + if (xPropInfo.is()) { - text::TextContentAnchorType eAnchorType; - xPropSet->getPropertyValue("AnchorType") >>= eAnchorType; - bool bInline = eAnchorType == text::TextContentAnchorType_AS_CHARACTER; + bool bInline = false; + if (xPropInfo->hasPropertyByName("AnchorType")) + { + text::TextContentAnchorType eAnchorType; + xPropSet->getPropertyValue("AnchorType") >>= eAnchorType; + bInline = eAnchorType == text::TextContentAnchorType_AS_CHARACTER; + } + mpEscherEx->OpenContainer( ESCHER_SpContainer ); if(bInline) { @@ -812,20 +817,14 @@ void ImplEESdrWriter::ImplWritePage( { ImplInitPageValues(); - sal_uInt32 nLastPer = 0, nShapes = mXShapes->getCount(); + const sal_uInt32 nShapes = mXShapes->getCount(); for( sal_uInt32 n = 0; n < nShapes; ++n ) { - sal_uInt32 nPer = ( 5 * n ) / nShapes; - if( nPer != nLastPer ) - { - nLastPer = nPer; - } - ImplEESdrObject aObj( *this, *o3tl::doAccess<Reference<XShape>>( mXShapes->getByIndex( n )) ); if( aObj.IsValid() ) { - ImplWriteShape( aObj, rSolverContainer ); + ImplWriteShape( aObj, rSolverContainer, true ); } } } diff --git a/include/oox/token/relationship.hxx b/include/oox/token/relationship.hxx index ae1580bf2bc5..adc25f4a73b6 100644 --- a/include/oox/token/relationship.hxx +++ b/include/oox/token/relationship.hxx @@ -23,6 +23,7 @@ enum class Relationship COMMENTS, COMMENTAUTHORS, CONTROL, + CTRLPROP, CUSTOMXML, CUSTOMXMLPROPS, DIAGRAMCOLORS, diff --git a/oox/source/token/relationship.inc b/oox/source/token/relationship.inc index 9b163038b169..2b973ded1653 100644 --- a/oox/source/token/relationship.inc +++ b/oox/source/token/relationship.inc @@ -3,6 +3,7 @@ {Relationship::COMMENTS, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"}, {Relationship::COMMENTAUTHORS, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/commentAuthors"}, {Relationship::CONTROL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/control"}, +{Relationship::CTRLPROP, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp"}, {Relationship::CUSTOMXML, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml"}, {Relationship::CUSTOMXMLPROPS, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps"}, {Relationship::DIAGRAMCOLORS, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramColors"}, diff --git a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx index c1e67ffeaf5b..4eb91066b865 100644 --- a/sc/source/filter/excel/excdoc.cxx +++ b/sc/source/filter/excel/excdoc.cxx @@ -689,8 +689,11 @@ void ExcTable::WriteXml( XclExpXmlStream& rStrm ) rStrm.PushStream( pWorksheet ); pWorksheet->startElement( XML_worksheet, - XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)).toUtf8(), - FSNS(XML_xmlns, XML_r), rStrm.getNamespaceURL(OOX_NS(officeRel)).toUtf8() ); + XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)).toUtf8(), + FSNS(XML_xmlns, XML_r), rStrm.getNamespaceURL(OOX_NS(officeRel)).toUtf8(), + FSNS(XML_xmlns, XML_xdr), "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing", // rStrm.getNamespaceURL(OOX_NS(xm)).toUtf8() -> "http://schemas.microsoft.com/office/excel/2006/main", + FSNS(XML_xmlns, XML_x14), rStrm.getNamespaceURL(OOX_NS(xls14Lst)).toUtf8(), + FSNS(XML_xmlns, XML_mc), rStrm.getNamespaceURL(OOX_NS(mce)).toUtf8()); SetCurrScTab( mnScTab ); if (mxCellTable) diff --git a/sc/source/filter/excel/xeescher.cxx b/sc/source/filter/excel/xeescher.cxx index 82aa24262314..6a7f4fa5fb9e 100644 --- a/sc/source/filter/excel/xeescher.cxx +++ b/sc/source/filter/excel/xeescher.cxx @@ -147,7 +147,15 @@ void lcl_WriteAnchorVertex( sax_fastparser::FSHelperPtr const & rComments, const rComments->endElement( FSNS( XML_xdr, XML_rowOff ) ); } -void lcl_GetFromTo( const XclExpRoot& rRoot, const tools::Rectangle &aRect, sal_Int32 nTab, tools::Rectangle &aFrom, tools::Rectangle &aTo ) +long lcl_hmm2output(long value, bool bInEMU) +{ + if (bInEMU) + return oox::drawingml::convertHmmToEmu(value); + else + return lcl_hmm2px(value); +} + +void lcl_GetFromTo( const XclExpRoot& rRoot, const tools::Rectangle &aRect, sal_Int32 nTab, tools::Rectangle &aFrom, tools::Rectangle &aTo, bool bInEMU = false ) { sal_Int32 nCol = 0, nRow = 0; sal_Int32 nColOff = 0, nRowOff= 0; @@ -170,8 +178,8 @@ void lcl_GetFromTo( const XclExpRoot& rRoot, const tools::Rectangle &aRect, sal_ } if( r.Left() > aRect.Left() && r.Top() > aRect.Top() ) { - aFrom = tools::Rectangle( nCol-1, lcl_hmm2px( nColOff ), - nRow-1, lcl_hmm2px( nRowOff ) ); + aFrom = tools::Rectangle( nCol-1, lcl_hmm2output( nColOff, bInEMU ), + nRow-1, lcl_hmm2output( nRowOff, bInEMU ) ); break; } } @@ -193,8 +201,8 @@ void lcl_GetFromTo( const XclExpRoot& rRoot, const tools::Rectangle &aRect, sal_ } if( r.Left() < aRect.Left() && r.Top() > aRect.Top() ) { - aFrom = tools::Rectangle( nCol-1, lcl_hmm2px( nColOff ), - nRow-1, lcl_hmm2px( nRowOff ) ); + aFrom = tools::Rectangle( nCol-1, lcl_hmm2output( nColOff, bInEMU ), + nRow-1, lcl_hmm2output( nRowOff, bInEMU ) ); break; } } @@ -210,8 +218,8 @@ void lcl_GetFromTo( const XclExpRoot& rRoot, const tools::Rectangle &aRect, sal_ nRow++; if( r.Right() >= aRect.Right() && r.Bottom() >= aRect.Bottom() ) { - aTo = tools::Rectangle( nCol, lcl_hmm2px( aRect.Right() - r.Left() ), - nRow, lcl_hmm2px( aRect.Bottom() - r.Top() )); + aTo = tools::Rectangle( nCol, lcl_hmm2output( aRect.Right() - r.Left(), bInEMU ), + nRow, lcl_hmm2output( aRect.Bottom() - r.Top(), bInEMU )); break; } } @@ -227,8 +235,8 @@ void lcl_GetFromTo( const XclExpRoot& rRoot, const tools::Rectangle &aRect, sal_ nRow++; if( r.Right() < aRect.Right() && r.Bottom() >= aRect.Bottom() ) { - aTo = tools::Rectangle( nCol, lcl_hmm2px( r.Left() - aRect.Right() ), - nRow, lcl_hmm2px( aRect.Bottom() - r.Top() )); + aTo = tools::Rectangle( nCol, lcl_hmm2output( r.Left() - aRect.Right(), bInEMU ), + nRow, lcl_hmm2output( aRect.Bottom() - r.Top(), bInEMU )); break; } } @@ -456,6 +464,7 @@ XclExpControlHelper::~XclExpControlHelper() void XclExpControlHelper::ConvertSheetLinks( Reference< XShape > const & xShape ) { mxCellLink.reset(); + mxCellLinkAddress.SetInvalid(); mxSrcRange.reset(); mnEntryCount = 0; @@ -476,10 +485,9 @@ void XclExpControlHelper::ConvertSheetLinks( Reference< XShape > const & xShape CellAddress aApiAddress; if( aBindProp.GetProperty( aApiAddress, SC_UNONAME_BOUNDCELL ) ) { - ScAddress aCellLink; - ScUnoConversion::FillScAddress( aCellLink, aApiAddress ); - if( GetTabInfo().IsExportTab( aCellLink.Tab() ) ) - mxCellLink = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, aCellLink ); + ScUnoConversion::FillScAddress( mxCellLinkAddress, aApiAddress ); + if( GetTabInfo().IsExportTab( mxCellLinkAddress.Tab() ) ) + mxCellLink = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, mxCellLinkAddress ); } } } @@ -634,6 +642,7 @@ void XclExpOcxControlObj::WriteSubRecs( XclExpStream& rStrm ) XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< XShape > const & xShape , const tools::Rectangle* pChildAnchor ) : XclObj( rRoot, EXC_OBJTYPE_UNKNOWN, true ), XclMacroHelper( rRoot ), + mxShape( xShape ), meEventType( EXC_TBX_EVENT_ACTION ), mnHeight( 0 ), mnState( 0 ), @@ -647,7 +656,10 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< mbFlatButton( false ), mbFlatBorder( false ), mbMultiSel( false ), - mbScrollHor( false ) + mbScrollHor( false ), + mbPrint( false ), + mbVisible( false ), + mnShapeId( 0 ) { namespace FormCompType = css::form::FormComponentType; namespace AwtVisualEffect = css::awt::VisualEffect; @@ -683,7 +695,8 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< // OBJ record flags SetLocked( true ); - SetPrintable( aCtrlProp.GetBoolProperty( "Printable" ) ); + mbPrint = aCtrlProp.GetBoolProperty( "Printable" ); + SetPrintable( mbPrint ); SetAutoFill( false ); SetAutoLine( false ); @@ -691,8 +704,8 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< mrEscherEx.OpenContainer( ESCHER_SpContainer ); mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty ); EscherPropertyContainer aPropOpt; - bool bVisible = aCtrlProp.GetBoolProperty( "EnableVisible" ); - aPropOpt.AddOpt( ESCHER_Prop_fPrint, bVisible ? 0x00080000 : 0x00080002 ); // visible flag + mbVisible = aCtrlProp.GetBoolProperty( "EnableVisible" ); + aPropOpt.AddOpt( ESCHER_Prop_fPrint, mbVisible ? 0x00080000 : 0x00080002 ); // visible flag aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01000100 ); // bool field aPropOpt.AddOpt( ESCHER_Prop_lTxid, 0 ); // Text ID @@ -702,9 +715,8 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field // #i51348# name of the control, may overwrite shape name - OUString aCtrlName; - if( aCtrlProp.GetProperty( aCtrlName, "Name" ) && !aCtrlName.isEmpty() ) - aPropOpt.AddOpt( ESCHER_Prop_wzName, aCtrlName ); + if( aCtrlProp.GetProperty( msCtrlName, "Name" ) && !msCtrlName.isEmpty() ) + aPropOpt.AddOpt( ESCHER_Prop_wzName, msCtrlName ); //Export description as alt text if( SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape ) ) @@ -726,8 +738,7 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< mrEscherEx.UpdateDffFragmentEnd(); // control label - OUString aString; - if( aCtrlProp.GetProperty( aString, "Label" ) ) + if( aCtrlProp.GetProperty( msLabel, "Label" ) ) { /* Be sure to construct the MSODRAWING record containing the ClientTextbox atom after the base OBJ's MSODRAWING record data is @@ -737,7 +748,7 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< mrEscherEx.UpdateDffFragmentEnd(); sal_uInt16 nXclFont = EXC_FONT_APP; - if( !aString.isEmpty() ) + if( !msLabel.isEmpty() ) { XclFontData aFontData; GetFontPropSetHelper().ReadFontProperties( aFontData, aCtrlProp, EXC_FONTPROPSET_CONTROL ); @@ -745,7 +756,7 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< nXclFont = GetFontBuffer().Insert( aFontData, EXC_COLOR_CTRLTEXT ); } - pTxo.reset( new XclTxo( aString, nXclFont ) ); + pTxo.reset( new XclTxo( msLabel, nXclFont ) ); pTxo->SetHorAlign( (mnObjType == EXC_OBJTYPE_BUTTON) ? EXC_OBJ_HOR_CENTER : EXC_OBJ_HOR_LEFT ); pTxo->SetVerAlign( EXC_OBJ_VER_CENTER ); } @@ -882,6 +893,29 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< break; } + { + Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( xShape ); + if( xCtrlModel.is() ) + { + Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY ); + if( xBindable.is() ) + { + Reference< XServiceInfo > xServInfo( xBindable->getValueBinding(), UNO_QUERY ); + if( xServInfo.is() && xServInfo->supportsService( SC_SERVICENAME_VALBIND ) ) + { + ScfPropertySet aBindProp( xServInfo ); + CellAddress aApiAddress; + if( aBindProp.GetProperty( aApiAddress, SC_UNONAME_BOUNDCELL ) ) + { + ScUnoConversion::FillScAddress( mxCellLinkAddress, aApiAddress ); + if( SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape ) ) + lcl_GetFromTo( rRoot, pSdrObj->GetLogicRect(), mxCellLinkAddress.Tab(), maAreaFrom, maAreaTo, true ); + } + } + } + } + } + // spreadsheet links ConvertSheetLinks( xShape ); } @@ -1053,6 +1087,275 @@ void XclExpTbxControlObj::WriteSbs( XclExpStream& rStrm ) rStrm.EndRecord(); } +void XclExpTbxControlObj::setShapeId(sal_Int32 aShapeId) +{ + mnShapeId = aShapeId; +} + +// save into xl\drawings\drawing1.xml +void XclExpTbxControlObj::SaveXml( XclExpXmlStream& rStrm ) +{ + sax_fastparser::FSHelperPtr& pDrawing = rStrm.GetCurrentStream(); + + pDrawing->startElement(FSNS(XML_mc, XML_AlternateContent), + FSNS(XML_xmlns, XML_mc), rStrm.getNamespaceURL(OOX_NS(mce)).toUtf8()); + pDrawing->startElement(FSNS(XML_mc, XML_Choice), + FSNS(XML_xmlns, XML_a14), rStrm.getNamespaceURL(OOX_NS(a14)).toUtf8(), + XML_Requires, "a14"); + + pDrawing->startElement(FSNS(XML_xdr, XML_twoCellAnchor), XML_editAs, "oneCell"); + { + pDrawing->startElement(FSNS(XML_xdr, XML_from)); + lcl_WriteAnchorVertex(pDrawing, maAreaFrom); + pDrawing->endElement(FSNS(XML_xdr, XML_from)); + pDrawing->startElement(FSNS(XML_xdr, XML_to)); + lcl_WriteAnchorVertex(pDrawing, maAreaTo); + pDrawing->endElement(FSNS(XML_xdr, XML_to)); + + pDrawing->startElement(FSNS(XML_xdr, XML_sp)); + { + // xdr:nvSpPr + pDrawing->startElement(FSNS(XML_xdr, XML_nvSpPr)); + { + pDrawing->singleElement(FSNS(XML_xdr, XML_cNvPr), + XML_id, OString::number(mnShapeId).getStr(), + XML_name, msCtrlName.toUtf8(), // control name + XML_descr, msLabel.toUtf8(), // description as alt text + XML_hidden, mbVisible ? "0" : "1"); + pDrawing->singleElement(FSNS(XML_xdr, XML_cNvSpPr)); + } + pDrawing->endElement(FSNS(XML_xdr, XML_nvSpPr)); + + // xdr:spPr + pDrawing->startElement(FSNS(XML_xdr, XML_spPr)); + { + // a:xfrm + pDrawing->startElement(FSNS(XML_a, XML_xfrm)); + { + pDrawing->singleElement(FSNS(XML_a, XML_off), + XML_x, "0", + XML_y, "0"); + pDrawing->singleElement(FSNS(XML_a, XML_ext), + XML_cx, "0", + XML_cy, "0"); + } + pDrawing->endElement(FSNS(XML_a, XML_xfrm)); + + // a:prstGeom + pDrawing->startElement(FSNS(XML_a, XML_prstGeom), XML_prst, "rect"); + { + pDrawing->singleElement(FSNS(XML_a, XML_avLst)); + } + pDrawing->endElement(FSNS(XML_a, XML_prstGeom)); + } + pDrawing->endElement(FSNS(XML_xdr, XML_spPr)); + + // xdr:txBody + { + pDrawing->startElement(FSNS(XML_xdr, XML_txBody)); + +#define DEFLRINS 254 +#define DEFTBINS 127 + sal_Int32 nLeft, nRight, nTop, nBottom; + nLeft = nRight = DEFLRINS; + nTop = nBottom = DEFTBINS; + + // top inset looks a bit different compared to ppt export + // check if something related doesn't work as expected + Reference< XPropertySet > rXPropSet(mxShape, UNO_QUERY); + + try + { + css::uno::Any mAny; + + mAny = rXPropSet->getPropertyValue("TextLeftDistance"); + if (mAny.hasValue()) + mAny >>= nLeft; + + mAny = rXPropSet->getPropertyValue("TextRightDistance"); + if (mAny.hasValue()) + mAny >>= nRight; + + mAny = rXPropSet->getPropertyValue("TextUpperDistance"); + if (mAny.hasValue()) + mAny >>= nTop; + + mAny = rXPropSet->getPropertyValue("TextLowerDistance"); + if (mAny.hasValue()) + mAny >>= nBottom; + } + catch (...) + { + } + + // Specifies the inset of the bounding rectangle. + // Insets are used just as internal margins for text boxes within shapes. + // If this attribute is omitted, then a value of 45720 or 0.05 inches is implied. + pDrawing->startElementNS(XML_a, XML_bodyPr, + XML_lIns, (nLeft != DEFLRINS) ? OString::number(oox::drawingml::convertHmmToEmu(nLeft)).getStr() : nullptr, + XML_rIns, (nRight != DEFLRINS) ? OString::number(oox::drawingml::convertHmmToEmu(nRight)).getStr() : nullptr, + XML_tIns, (nTop != DEFTBINS) ? OString::number(oox::drawingml::convertHmmToEmu(nTop)).getStr() : nullptr, + XML_bIns, (nBottom != DEFTBINS) ? OString::number(oox::drawingml::convertHmmToEmu(nBottom)).getStr() : nullptr, + XML_anchor, "ctr"); + + { + bool bTextAutoGrowHeight = false; + + try + { + css::uno::Any mAny; + + mAny = rXPropSet->getPropertyValue("TextAutoGrowHeight"); + if (mAny.hasValue()) + mAny >>= bTextAutoGrowHeight; + } + catch (...) + { + } + + pDrawing->singleElementNS(XML_a, (bTextAutoGrowHeight ? XML_spAutoFit : XML_noAutofit)); + } + + pDrawing->endElementNS(XML_a, XML_bodyPr); + + { + pDrawing->startElementNS(XML_a, XML_p); + pDrawing->startElementNS(XML_a, XML_r); + pDrawing->startElementNS(XML_a, XML_t); + pDrawing->write(msLabel.toUtf8()); + pDrawing->endElementNS(XML_a, XML_t); + pDrawing->endElementNS(XML_a, XML_r); + pDrawing->endElementNS(XML_a, XML_p); + } + + pDrawing->endElement(FSNS(XML_xdr, XML_txBody)); + } + } + pDrawing->endElement(FSNS(XML_xdr, XML_sp)); + pDrawing->singleElement(FSNS(XML_xdr, XML_clientData)); + } + pDrawing->endElement(FSNS(XML_xdr, XML_twoCellAnchor)); + pDrawing->endElement( FSNS( XML_mc, XML_Choice ) ); + pDrawing->endElement( FSNS( XML_mc, XML_AlternateContent ) ); +} + +// output into ctrlProp1.xml +OUString XclExpTbxControlObj::SaveControlPropertiesXml(XclExpXmlStream& rStrm) const +{ + OUString sIdFormControlPr; + + switch (mnObjType) + { + case EXC_OBJTYPE_CHECKBOX: + { + const sal_Int32 nDrawing = XclExpObjList::getNewDrawingUniqueId(); + sax_fastparser::FSHelperPtr pFormControl = rStrm.CreateOutputStream( + XclXmlUtils::GetStreamName( "xl/", "ctrlProps/ctrlProps", nDrawing ), + XclXmlUtils::GetStreamName( "../", "ctrlProps/ctrlProps", nDrawing ), + rStrm.GetCurrentStream()->getOutputStream(), + "application/vnd.ms-excel.controlproperties+xml", + OUStringToOString(oox::getRelationship(Relationship::CTRLPROP), RTL_TEXTENCODING_UTF8).getStr(), + &sIdFormControlPr ); + + rStrm.PushStream( pFormControl ); + // checkbox + // <formControlPr + // xmlns="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" + // objectType="CheckBox" checked="Checked" lockText="1" noThreeD="1"/> + // + pFormControl->write("<formControlPr xmlns=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main\" objectType=\"CheckBox\""); + if (mnState == EXC_OBJ_CHECKBOX_CHECKED) + pFormControl->write(" checked=\"Checked\""); + + pFormControl->write(" autoLine=\"false\""); + + if (mbPrint) + pFormControl->write(" print=\"true\""); + else + pFormControl->write(" print=\"false\""); + + if (mxCellLinkAddress.IsValid()) + { + OUString aCellLink = mxCellLinkAddress.Format(ScRefFlags::ADDR_ABS, + &GetDoc(), + ScAddress::Details(::formula::FormulaGrammar::CONV_XL_A1)); + + // "Sheet1!$C$5" + pFormControl->write(" fmlaLink=\""); + if (aCellLink.indexOf('!') < 0) + { + pFormControl->write(GetTabInfo().GetScTabName( mxCellLinkAddress.Tab() ).toUtf8()); + pFormControl->write("!"); + } + pFormControl->write(aCellLink); + pFormControl->write("\""); + } + + pFormControl->write(" lockText=\"1\" noThreeD=\"1\"/>"); + rStrm.PopStream(); + + break; + } + } + + return sIdFormControlPr; +} + +// output into sheet1.xml +void XclExpTbxControlObj::SaveSheetXml(XclExpXmlStream& rStrm, const OUString& aIdFormControlPr) const +{ + switch (mnObjType) + { + case EXC_OBJTYPE_CHECKBOX: + { + sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); + + rWorksheet->startElement(FSNS(XML_mc, XML_AlternateContent), + FSNS(XML_xmlns, XML_mc), rStrm.getNamespaceURL(OOX_NS(mce)).toUtf8()); + rWorksheet->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, "x14"); + + rWorksheet->startElement( + XML_control, + XML_shapeId, OString::number(mnShapeId).getStr(), + FSNS(XML_r, XML_id), aIdFormControlPr.toUtf8(), + XML_name, msLabel.toUtf8()); // text to display with checkbox button + + rWorksheet->write("<controlPr defaultSize=\"0\" locked=\"1\" autoFill=\"0\" autoLine=\"0\" autoPict=\"0\""); + + if (mbPrint) + rWorksheet->write(" print=\"true\""); + else + rWorksheet->write(" print=\"false\""); + + if (!msCtrlName.isEmpty()) + { + rWorksheet->write(" altText=\""); + rWorksheet->write(msCtrlName.toUtf8()); // alt text + rWorksheet->write("\""); + } + + rWorksheet->write(">"); + + rWorksheet->startElement(XML_anchor, XML_moveWithCells, "true", XML_sizeWithCells, "false"); + rWorksheet->startElement(XML_from); + lcl_WriteAnchorVertex(rWorksheet, maAreaFrom); + rWorksheet->endElement(XML_from); + rWorksheet->startElement(XML_to); + lcl_WriteAnchorVertex(rWorksheet, maAreaTo); + rWorksheet->endElement(XML_to); + rWorksheet->endElement( XML_anchor ); + + rWorksheet->write("</controlPr>"); + + rWorksheet->endElement(XML_control); + rWorksheet->endElement( FSNS( XML_mc, XML_Choice ) ); + rWorksheet->endElement( FSNS( XML_mc, XML_AlternateContent ) ); + + break; + } + } +} + //#endif XclExpChartObj::XclExpChartObj( XclExpObjectManager& rObjMgr, Reference< XShape > const & xShape, const tools::Rectangle* pChildAnchor, ScDocument* pDoc ) : diff --git a/sc/source/filter/inc/xcl97rec.hxx b/sc/source/filter/inc/xcl97rec.hxx index 3306a72a2007..90ca18c8990c 100644 --- a/sc/source/filter/inc/xcl97rec.hxx +++ b/sc/source/filter/inc/xcl97rec.hxx @@ -84,6 +84,8 @@ public: static void ResetCounters(); + static sal_Int32 getNewDrawingUniqueId() { return ++mnDrawingMLCount; } + private: static sal_Int32 mnDrawingMLCount, mnVmlCount; SCTAB mnScTab; diff --git a/sc/source/filter/inc/xeescher.hxx b/sc/source/filter/inc/xeescher.hxx index a3c7e70abbd0..1a08b6db9886 100644 --- a/sc/source/filter/inc/xeescher.hxx +++ b/sc/source/filter/inc/xeescher.hxx @@ -188,6 +188,8 @@ private: XclTokenArrayRef mxCellLink; /// Formula for linked cell. XclTokenArrayRef mxSrcRange; /// Formula for source data range. sal_uInt16 mnEntryCount; /// Number of entries in source range. +protected: + ScAddress mxCellLinkAddress; }; class XclMacroHelper : public XclExpControlHelper @@ -255,6 +257,13 @@ public: @return true = The passed event descriptor was valid, macro name has been found. */ bool SetMacroLink( const css::script::ScriptEventDescriptor& rEvent ); + virtual void SaveXml( XclExpXmlStream& rStrm ) override; + + OUString SaveControlPropertiesXml(XclExpXmlStream& rStrm) const; + void SaveSheetXml(XclExpXmlStream& rStrm, const OUString& aIdFormControlPr) const; + + void setShapeId(sal_Int32 aShapeId); + private: virtual void WriteSubRecs( XclExpStream& rStrm ) override; @@ -264,6 +273,7 @@ private: void WriteSbs( XclExpStream& rStrm ); private: + const css::uno::Reference< css::drawing::XShape > mxShape; ScfInt16Vec maMultiSel; /// Indexes of all selected entries in a multi selection. XclTbxEventType meEventType; /// Type of supported macro event. sal_Int32 mnHeight; /// Height of the control. @@ -279,6 +289,13 @@ private: bool mbFlatBorder; /// False = 3D border style; True = Flat border style. bool mbMultiSel; /// true = Multi selection in listbox. bool mbScrollHor; /// Scrollbar: true = horizontal. + bool mbPrint; + bool mbVisible; + OUString msCtrlName; + OUString msLabel; + sal_Int32 mnShapeId; + tools::Rectangle maAreaFrom; + tools::Rectangle maAreaTo; }; //#endif diff --git a/sc/source/filter/xcl97/xcl97rec.cxx b/sc/source/filter/xcl97/xcl97rec.cxx index a5b3e5de9e35..88cdd82cdcd6 100644 --- a/sc/source/filter/xcl97/xcl97rec.cxx +++ b/sc/source/filter/xcl97/xcl97rec.cxx @@ -153,6 +153,17 @@ void XclExpObjList::Save( XclExpStream& rStrm ) namespace { +bool IsFormControlObject( const XclObj *rObj ) +{ + switch( rObj->GetObjType() ) + { + case EXC_OBJTYPE_CHECKBOX: + return true; + default: + return false; + } +} + bool IsVmlObject( const XclObj *rObj ) { switch( rObj->GetObjType() ) @@ -211,7 +222,7 @@ bool IsValidObject( const XclObj& rObj ) return true; } -void SaveDrawingMLObjects( XclExpObjList& rList, XclExpXmlStream& rStrm, sal_Int32& nDrawingMLCount ) +void SaveDrawingMLObjects( XclExpObjList& rList, XclExpXmlStream& rStrm ) { std::vector<XclObj*> aList; aList.reserve(rList.size()); @@ -226,7 +237,7 @@ void SaveDrawingMLObjects( XclExpObjList& rList, XclExpXmlStream& rStrm, sal_Int if (aList.empty()) return; - sal_Int32 nDrawing = ++nDrawingMLCount; + sal_Int32 nDrawing = XclExpObjList::getNewDrawingUniqueId(); OUString sId; sax_fastparser::FSHelperPtr pDrawing = rStrm.CreateOutputStream( XclXmlUtils::GetStreamName( "xl/", "drawings/drawing", nDrawing ), @@ -244,14 +255,54 @@ void SaveDrawingMLObjects( XclExpObjList& rList, XclExpXmlStream& rStrm, sal_Int FSNS(XML_xmlns, XML_a), rStrm.getNamespaceURL(OOX_NS(dml)).toUtf8(), FSNS(XML_xmlns, XML_r), rStrm.getNamespaceURL(OOX_NS(officeRel)).toUtf8() ); + sal_Int32 nShapeId = 1000; // unique id of the shape inside one worksheet (not the whole document) for (const auto& rpObj : aList) + { + // validate shapeId + if ( IsFormControlObject( rpObj ) ) + { + XclExpTbxControlObj* pXclExpTbxControlObj = dynamic_cast<XclExpTbxControlObj*>(rpObj); + if (pXclExpTbxControlObj) + { + pXclExpTbxControlObj->setShapeId(++nShapeId); + } + } + rpObj->SaveXml(rStrm); + } pDrawing->endElement( FSNS( XML_xdr, XML_wsDr ) ); rStrm.PopStream(); } +void SaveFormControlObjects(XclExpObjList& rList, XclExpXmlStream& rStrm) +{ + sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); + + rWorksheet->startElement(FSNS(XML_mc, XML_AlternateContent), + FSNS(XML_xmlns, XML_mc), rStrm.getNamespaceURL(OOX_NS(mce)).toUtf8()); + rWorksheet->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, "x14"); + rWorksheet->startElement(XML_controls); + + for (const auto& rxObj : rList) + { + if (IsFormControlObject(rxObj.get())) + { + XclExpTbxControlObj* pXclExpTbxControlObj = dynamic_cast<XclExpTbxControlObj*>(rxObj.get()); + if (pXclExpTbxControlObj) + { + const OUString aIdFormControlPr = pXclExpTbxControlObj->SaveControlPropertiesXml(rStrm); + pXclExpTbxControlObj->SaveSheetXml(rStrm, aIdFormControlPr); + } + } + } + + rWorksheet->endElement(XML_controls); + rWorksheet->endElement(FSNS(XML_mc, XML_Choice)); + rWorksheet->endElement(FSNS(XML_mc, XML_AlternateContent)); +} + void SaveVmlObjects( XclExpObjList& rList, XclExpXmlStream& rStrm, sal_Int32& nVmlCount ) { if( GetVmlObjectCount( rList ) == 0 ) @@ -298,7 +349,8 @@ void XclExpObjList::SaveXml( XclExpXmlStream& rStrm ) if( maObjs.empty()) return; - SaveDrawingMLObjects( *this, rStrm, mnDrawingMLCount ); + SaveDrawingMLObjects( *this, rStrm ); + SaveFormControlObjects( *this, rStrm ); SaveVmlObjects( *this, rStrm, mnVmlCount ); } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits