chart2/Library_chartcontroller.mk                             |    5 
 chart2/Library_chartcore.mk                                   |    5 
 chart2/source/controller/dialogs/DataBrowser.cxx              |    2 
 chart2/source/controller/dialogs/DataBrowserModel.cxx         |    2 
 chart2/source/controller/dialogs/DialogModel.hxx              |    2 
 chart2/source/controller/inc/dlg_CreationWizard.hxx           |    2 
 chart2/source/controller/inc/res_ErrorBar.hxx                 |    2 
 chart2/source/inc/DataBrowserModel.hxx                        |    6 
 chart2/source/inc/InternalDataProvider.hxx                    |    8 
 chart2/source/inc/RangeSelectionHelper.hxx                    |    4 
 chart2/source/inc/RangeSelectionListener.hxx                  |    4 
 chart2/source/inc/TimerTriggeredControllerLock.hxx            |    4 
 chart2/source/model/main/ChartModel.cxx                       |    3 
 chart2/source/tools/InternalDataProvider.cxx                  |   15 
 offapi/com/sun/star/chart2/XInternalDataProvider.idl          |    7 
 solenv/clang-format/excludelist                               |    4 
 sw/qa/uibase/shells/data/docStructureChartExampleOriginal.odt |binary
 sw/qa/uibase/shells/shells.cxx                                |  196 +++
 sw/source/uibase/shells/textsh1.cxx                           |  585 +++++++++-
 sw/source/uibase/uno/loktxdoc.cxx                             |  139 ++
 20 files changed, 974 insertions(+), 21 deletions(-)

New commits:
commit d9338fcf8f15a7e32a9de3e7249c925fd768ffc9
Author:     Attila Szűcs <attila.sz...@collabora.com>
AuthorDate: Thu Jul 25 06:21:35 2024 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Thu Sep 12 22:14:04 2024 +0200

    SW: extract transform charts (using dialog code)
    
    Implemented chart data extraction, and transformation
    added insert/delete/modify row/column, and the ability to set
    resize data table
    setcolumndesc / setrowdesc .. for 1 descriptor,
    or with multiple descriptor to set
    set 1 cell value, or set the whole table cells values.
    it will resize the table, but you can still use partial arrays
    like
                "data": [ [ 1,2,3,4 ],
                          [ 2,3,4,5 ],
                          [ 3 ],
                          [ 4,5,6,7 ],
                          [ 2,2,1 ],
                          [ 5,6,7,8 ] ],
    that means the 3. row 2,3,4th cell will not be overwritten.
    
    for insert column, it call codes from DataBrowserModel.
    (used by dialog code)
    
    added tests, fixed a contentcontrol date problem
    
    2. commit (made by Caolan) squashed into 1. commit:
    WIP hack this to link
    
    move stuff from chartcontroller to chartcore and adjust visibility
    until it links at least
    
    Change-Id: I5529f4da33f046eef7e947d755e29486fa966274
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172849
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/chart2/Library_chartcontroller.mk 
b/chart2/Library_chartcontroller.mk
index ca50d52a1fd9..b2d05298c237 100644
--- a/chart2/Library_chartcontroller.mk
+++ b/chart2/Library_chartcontroller.mk
@@ -100,8 +100,6 @@ $(eval $(call 
gb_Library_add_exception_objects,chartcontroller,\
     chart2/source/controller/dialogs/ChartResourceGroups \
     chart2/source/controller/dialogs/ChartTypeDialogController \
     chart2/source/controller/dialogs/DataBrowser \
-    chart2/source/controller/dialogs/DataBrowserModel \
-    chart2/source/controller/dialogs/DialogModel \
     chart2/source/controller/dialogs/dlg_ChartType \
     chart2/source/controller/dialogs/dlg_ChartType_UNO \
     chart2/source/controller/dialogs/dlg_CreationWizard \
@@ -120,8 +118,6 @@ $(eval $(call 
gb_Library_add_exception_objects,chartcontroller,\
     chart2/source/controller/dialogs/dlg_ShapeParagraph \
     chart2/source/controller/dialogs/dlg_View3D \
     chart2/source/controller/dialogs/ObjectNameProvider \
-    chart2/source/controller/dialogs/RangeSelectionHelper \
-    chart2/source/controller/dialogs/RangeSelectionListener \
     chart2/source/controller/dialogs/res_BarGeometry \
     chart2/source/controller/dialogs/res_DataLabel \
     chart2/source/controller/dialogs/res_DataTableProperties \
@@ -130,7 +126,6 @@ $(eval $(call 
gb_Library_add_exception_objects,chartcontroller,\
     chart2/source/controller/dialogs/res_Titles \
     chart2/source/controller/dialogs/res_Trendline \
     chart2/source/controller/dialogs/TextDirectionListBox \
-    chart2/source/controller/dialogs/TimerTriggeredControllerLock \
     chart2/source/controller/dialogs/TitleDialogData \
     chart2/source/controller/dialogs/tp_3D_SceneAppearance \
     chart2/source/controller/dialogs/tp_3D_SceneGeometry \
diff --git a/chart2/Library_chartcore.mk b/chart2/Library_chartcore.mk
index b61390ec42ea..ad204c1ef094 100644
--- a/chart2/Library_chartcore.mk
+++ b/chart2/Library_chartcore.mk
@@ -62,6 +62,11 @@ $(eval $(call 
gb_Library_set_componentfile,chartcore,chart2/source/chartcore,ser
 
 # view pieces ...
 $(eval $(call gb_Library_add_exception_objects,chartcore,\
+    chart2/source/controller/dialogs/DataBrowserModel \
+    chart2/source/controller/dialogs/DialogModel \
+    chart2/source/controller/dialogs/RangeSelectionHelper \
+    chart2/source/controller/dialogs/RangeSelectionListener \
+    chart2/source/controller/dialogs/TimerTriggeredControllerLock \
     chart2/source/view/axes/DateHelper \
     chart2/source/view/axes/DateScaling \
     chart2/source/view/axes/MinimumAndMaximumSupplier \
diff --git a/chart2/source/controller/dialogs/DataBrowser.cxx 
b/chart2/source/controller/dialogs/DataBrowser.cxx
index 30182b95eeb8..4af7753dcafa 100644
--- a/chart2/source/controller/dialogs/DataBrowser.cxx
+++ b/chart2/source/controller/dialogs/DataBrowser.cxx
@@ -20,7 +20,7 @@
 #include <svl/zforlist.hxx>
 
 #include "DataBrowser.hxx"
-#include "DataBrowserModel.hxx"
+#include <DataBrowserModel.hxx>
 #include <strings.hrc>
 #include <DataSeries.hxx>
 #include <DataSeriesHelper.hxx>
diff --git a/chart2/source/controller/dialogs/DataBrowserModel.cxx 
b/chart2/source/controller/dialogs/DataBrowserModel.cxx
index 63ec6f31fc16..55f483179880 100644
--- a/chart2/source/controller/dialogs/DataBrowserModel.cxx
+++ b/chart2/source/controller/dialogs/DataBrowserModel.cxx
@@ -17,8 +17,8 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#include "DataBrowserModel.hxx"
 #include "DialogModel.hxx"
+#include <DataBrowserModel.hxx>
 #include <ChartModelHelper.hxx>
 #include <ChartType.hxx>
 #include <ChartTypeManager.hxx>
diff --git a/chart2/source/controller/dialogs/DialogModel.hxx 
b/chart2/source/controller/dialogs/DialogModel.hxx
index 325cffe06773..8711185e742e 100644
--- a/chart2/source/controller/dialogs/DialogModel.hxx
+++ b/chart2/source/controller/dialogs/DialogModel.hxx
@@ -61,7 +61,7 @@ struct DialogModelTimeBasedInfo
     sal_Int32 nEnd;
 };
 
-class DialogModel
+class OOO_DLLPUBLIC_CHARTTOOLS DialogModel
 {
 public:
     explicit DialogModel( rtl::Reference<::chart::ChartModel> xChartDocument );
diff --git a/chart2/source/controller/inc/dlg_CreationWizard.hxx 
b/chart2/source/controller/inc/dlg_CreationWizard.hxx
index 1b782632f4d3..556c1ca81bb3 100644
--- a/chart2/source/controller/inc/dlg_CreationWizard.hxx
+++ b/chart2/source/controller/inc/dlg_CreationWizard.hxx
@@ -19,7 +19,7 @@
 
 #pragma once
 
-#include "TimerTriggeredControllerLock.hxx"
+#include <TimerTriggeredControllerLock.hxx>
 #include "TabPageNotifiable.hxx"
 
 #include <rtl/ref.hxx>
diff --git a/chart2/source/controller/inc/res_ErrorBar.hxx 
b/chart2/source/controller/inc/res_ErrorBar.hxx
index c3521d5ba087..2a1f3645a775 100644
--- a/chart2/source/controller/inc/res_ErrorBar.hxx
+++ b/chart2/source/controller/inc/res_ErrorBar.hxx
@@ -22,7 +22,7 @@
 #include <tools/link.hxx>
 #include <svl/itemset.hxx>
 #include <svx/chrtitem.hxx>
-#include "RangeSelectionListener.hxx"
+#include <RangeSelectionListener.hxx>
 #include <rtl/ref.hxx>
 
 namespace com::sun::star::chart2 { class XChartDocument; }
diff --git a/chart2/source/controller/dialogs/DataBrowserModel.hxx 
b/chart2/source/inc/DataBrowserModel.hxx
similarity index 98%
rename from chart2/source/controller/dialogs/DataBrowserModel.hxx
rename to chart2/source/inc/DataBrowserModel.hxx
index e3254851d002..16acb2de0b07 100644
--- a/chart2/source/controller/dialogs/DataBrowserModel.hxx
+++ b/chart2/source/inc/DataBrowserModel.hxx
@@ -18,8 +18,8 @@
  */
 #pragma once
 
-#include <DataSeries.hxx>
-#include <ChartType.hxx>
+#include "DataSeries.hxx"
+#include "ChartType.hxx"
 
 #include <com/sun/star/uno/Reference.hxx>
 #include <rtl/ref.hxx>
@@ -44,7 +44,7 @@ class ChartModel;
 class ChartType;
 class DataSeries;
 
-class DataBrowserModel final
+class OOO_DLLPUBLIC_CHARTTOOLS DataBrowserModel final
 {
 public:
     explicit DataBrowserModel(
diff --git a/chart2/source/inc/InternalDataProvider.hxx 
b/chart2/source/inc/InternalDataProvider.hxx
index a5032efcdab8..26a759c56865 100644
--- a/chart2/source/inc/InternalDataProvider.hxx
+++ b/chart2/source/inc/InternalDataProvider.hxx
@@ -19,6 +19,7 @@
 #pragma once
 
 #include "InternalData.hxx"
+#include <ChartModel.hxx>
 
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/chart/XDateCategories.hpp>
@@ -30,6 +31,7 @@
 #include <cppuhelper/implbase.hxx>
 #include <cppuhelper/weakref.hxx>
 #include <rtl/ref.hxx>
+#include <unotools/weakref.hxx>
 
 #include <map>
 
@@ -101,6 +103,7 @@ public:
     virtual void SAL_CALL swapDataPointWithNextOneForAllSequences( ::sal_Int32 
nAtIndex ) override;
     virtual void SAL_CALL registerDataSequenceForChanges(
         const css::uno::Reference< css::chart2::data::XDataSequence >& xSeq ) 
override;
+    virtual void SAL_CALL insertDataSeries( ::sal_Int32 nAfterIndex ) override;
 
     // ____ XDataProvider (base of XInternalDataProvider) ____
     virtual sal_Bool SAL_CALL createDataSourcePossible(
@@ -175,6 +178,8 @@ public:
     // css::lang::XInitialization:
     virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > 
& aArguments) override;
 
+    void setChartModel(ChartModel* pChartModel);
+
 private:
     void addDataSequenceToMap(
         const OUString & rRangeRepresentation,
@@ -213,6 +218,9 @@ private:
     tSequenceMap m_aSequenceMap;
     InternalData m_aInternalData;
     bool m_bDataInColumns;
+
+    // keep a weak reference to the owning m_xChartModel for insertDataSeries
+    unotools::WeakReference<ChartModel> m_xChartModel;
 };
 
 } //  namespace chart
diff --git a/chart2/source/controller/inc/RangeSelectionHelper.hxx 
b/chart2/source/inc/RangeSelectionHelper.hxx
similarity index 96%
rename from chart2/source/controller/inc/RangeSelectionHelper.hxx
rename to chart2/source/inc/RangeSelectionHelper.hxx
index 36fe0db99cce..3afc7fcb511a 100644
--- a/chart2/source/controller/inc/RangeSelectionHelper.hxx
+++ b/chart2/source/inc/RangeSelectionHelper.hxx
@@ -23,6 +23,8 @@
 #include <rtl/ustring.hxx>
 #include <rtl/ref.hxx>
 
+#include "charttoolsdllapi.hxx"
+
 namespace com::sun::star::beans { struct PropertyValue; }
 namespace com::sun::star::chart2 { class XChartDocument; }
 
@@ -38,7 +40,7 @@ namespace chart
 class ChartModel;
 class RangeSelectionListenerParent;
 
-class RangeSelectionHelper
+class OOO_DLLPUBLIC_CHARTTOOLS RangeSelectionHelper
 {
 public:
     explicit RangeSelectionHelper(
diff --git a/chart2/source/controller/inc/RangeSelectionListener.hxx 
b/chart2/source/inc/RangeSelectionListener.hxx
similarity index 96%
rename from chart2/source/controller/inc/RangeSelectionListener.hxx
rename to chart2/source/inc/RangeSelectionListener.hxx
index 0ca4644a96ad..7902ff2263a4 100644
--- a/chart2/source/controller/inc/RangeSelectionListener.hxx
+++ b/chart2/source/inc/RangeSelectionListener.hxx
@@ -18,7 +18,7 @@
  */
 #pragma once
 
-#include <ControllerLockGuard.hxx>
+#include "ControllerLockGuard.hxx"
 #include <cppuhelper/implbase.hxx>
 #include <com/sun/star/sheet/XRangeSelectionListener.hpp>
 #include <rtl/ref.hxx>
@@ -36,7 +36,7 @@ namespace chart
 {
 class ChartModel;
 
-class RangeSelectionListenerParent
+class OOO_DLLPUBLIC_CHARTTOOLS RangeSelectionListenerParent
 {
 public:
     virtual void listeningFinished(const OUString& rNewRange) = 0;
diff --git a/chart2/source/controller/inc/TimerTriggeredControllerLock.hxx 
b/chart2/source/inc/TimerTriggeredControllerLock.hxx
similarity index 93%
rename from chart2/source/controller/inc/TimerTriggeredControllerLock.hxx
rename to chart2/source/inc/TimerTriggeredControllerLock.hxx
index 49541b1552d4..7d56fd94369e 100644
--- a/chart2/source/controller/inc/TimerTriggeredControllerLock.hxx
+++ b/chart2/source/inc/TimerTriggeredControllerLock.hxx
@@ -24,6 +24,8 @@
 
 #include <memory>
 
+#include "charttoolsdllapi.hxx"
+
 namespace com::sun::star::frame
 {
 class XModel;
@@ -37,7 +39,7 @@ namespace chart
 {
 class ChartModel;
 
-class TimerTriggeredControllerLock final
+class OOO_DLLPUBLIC_CHARTTOOLS TimerTriggeredControllerLock final
 {
 public:
     TimerTriggeredControllerLock(rtl::Reference<::chart::ChartModel> xModel);
diff --git a/chart2/source/model/main/ChartModel.cxx 
b/chart2/source/model/main/ChartModel.cxx
index 6c4fe2dfa658..5e8b6526e760 100644
--- a/chart2/source/model/main/ChartModel.cxx
+++ b/chart2/source/model/main/ChartModel.cxx
@@ -743,7 +743,10 @@ void SAL_CALL ChartModel::createInternalDataProvider( 
sal_Bool bCloneExistingDat
         if( bCloneExistingData )
             m_xInternalDataProvider = 
ChartModelHelper::createInternalDataProvider( this, true );
         else
+        {
             m_xInternalDataProvider = 
ChartModelHelper::createInternalDataProvider( nullptr, true );
+            m_xInternalDataProvider->setChartModel(this);
+        }
         m_xDataProvider.set( m_xInternalDataProvider );
     }
     setModified( true );
diff --git a/chart2/source/tools/InternalDataProvider.cxx 
b/chart2/source/tools/InternalDataProvider.cxx
index 883920daa9fb..16a24836df0a 100644
--- a/chart2/source/tools/InternalDataProvider.cxx
+++ b/chart2/source/tools/InternalDataProvider.cxx
@@ -33,6 +33,7 @@
 #include <Diagram.hxx>
 #include <ExplicitCategoriesProvider.hxx>
 #include <BaseCoordinateSystem.hxx>
+#include <DataBrowserModel.hxx>
 #include <DataSeries.hxx>
 
 #include <com/sun/star/chart2/data/XDataSequence.hpp>
@@ -311,6 +312,7 @@ InternalDataProvider::InternalDataProvider(
 {
     if (!xModel.is())
         return;
+    m_xChartModel = xModel.get();
     try
     {
         rtl::Reference< Diagram > xDiagram( xModel->getFirstChartDiagram() );
@@ -406,6 +408,11 @@ InternalDataProvider::InternalDataProvider( const 
InternalDataProvider & rOther
 InternalDataProvider::~InternalDataProvider()
 {}
 
+void InternalDataProvider::setChartModel(ChartModel* pChartModel)
+{
+    m_xChartModel = pChartModel;
+}
+
 void InternalDataProvider::addDataSequenceToMap(
     const OUString & rRangeRepresentation,
     const Reference< chart2::data::XDataSequence > & xSequence )
@@ -1159,6 +1166,14 @@ void SAL_CALL 
InternalDataProvider::registerDataSequenceForChanges( const Refere
         addDataSequenceToMap( xSeq->getSourceRangeRepresentation(), xSeq );
 }
 
+void SAL_CALL InternalDataProvider::insertDataSeries(::sal_Int32 nAfterIndex)
+{
+    // call the dialog insertion
+    rtl::Reference<ChartModel> xChartModel(m_xChartModel);
+    DataBrowserModel* pDBM = new DataBrowserModel(xChartModel);
+    pDBM->insertDataSeries(nAfterIndex);
+}
+
 // ____ XRangeXMLConversion ____
 OUString SAL_CALL InternalDataProvider::convertRangeToXML( const OUString& 
aRangeRepresentation )
 {
diff --git a/offapi/com/sun/star/chart2/XInternalDataProvider.idl 
b/offapi/com/sun/star/chart2/XInternalDataProvider.idl
index 322c65240f09..4c97a1208ab2 100644
--- a/offapi/com/sun/star/chart2/XInternalDataProvider.idl
+++ b/offapi/com/sun/star/chart2/XInternalDataProvider.idl
@@ -71,6 +71,13 @@ interface XInternalDataProvider  : 
com::sun::star::chart2::data::XDataProvider
     @since OOo 3.3
     */
     void deleteComplexCategoryLevel( [in] long nLevel );
+
+    /** similar to insertSequence, but it also insert data series
+        and handle other things needed for the chart, like set color, format...
+        it calls the DataBrowserModel::insertDataSeries()
+        @since LibreOffice 25.2
+    */
+    void insertDataSeries( [in] long nAfterIndex );
 };
 
 } ; // chart2
diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist
index a944060b0329..5124958345d1 100644
--- a/solenv/clang-format/excludelist
+++ b/solenv/clang-format/excludelist
@@ -802,7 +802,6 @@ 
chart2/source/controller/dialogs/ChartTypeDialogController.cxx
 chart2/source/controller/dialogs/DataBrowser.cxx
 chart2/source/controller/dialogs/DataBrowser.hxx
 chart2/source/controller/dialogs/DataBrowserModel.cxx
-chart2/source/controller/dialogs/DataBrowserModel.hxx
 chart2/source/controller/dialogs/DialogModel.cxx
 chart2/source/controller/dialogs/DialogModel.hxx
 chart2/source/controller/dialogs/ObjectNameProvider.cxx
@@ -883,7 +882,6 @@ chart2/source/controller/inc/MultipleItemConverter.hxx
 chart2/source/controller/inc/ObjectHierarchy.hxx
 chart2/source/controller/inc/ObjectNameProvider.hxx
 chart2/source/controller/inc/PositionAndSizeHelper.hxx
-chart2/source/controller/inc/RangeSelectionHelper.hxx
 chart2/source/controller/inc/RegressionCurveItemConverter.hxx
 chart2/source/controller/inc/RegressionEquationItemConverter.hxx
 chart2/source/controller/inc/SelectionHelper.hxx
@@ -1003,6 +1001,7 @@ chart2/source/inc/ColorPerPointHelper.hxx
 chart2/source/inc/CommonConverters.hxx
 chart2/source/inc/CommonFunctors.hxx
 chart2/source/inc/ConfigColorScheme.hxx
+chart2/source/inc/DataBrowserModel.hxx
 chart2/source/inc/DataInterpreter.hxx
 chart2/source/inc/DataSeries.hxx
 chart2/source/inc/DataSeriesHelper.hxx
@@ -1040,6 +1039,7 @@ chart2/source/inc/PolynomialRegressionCurveCalculator.hxx
 chart2/source/inc/PotentialRegressionCurveCalculator.hxx
 chart2/source/inc/PropertyHelper.hxx
 chart2/source/inc/RangeHighlighter.hxx
+chart2/source/inc/RangeSelectionHelper.hxx
 chart2/source/inc/ReferenceSizeProvider.hxx
 chart2/source/inc/RegressionCalculationHelper.hxx
 chart2/source/inc/RegressionCurveCalculator.hxx
diff --git a/sw/qa/uibase/shells/data/docStructureChartExampleOriginal.odt 
b/sw/qa/uibase/shells/data/docStructureChartExampleOriginal.odt
new file mode 100644
index 000000000000..da775ecf4aaa
Binary files /dev/null and 
b/sw/qa/uibase/shells/data/docStructureChartExampleOriginal.odt differ
diff --git a/sw/qa/uibase/shells/shells.cxx b/sw/qa/uibase/shells/shells.cxx
index 2111cedf2502..f09e775d37b6 100644
--- a/sw/qa/uibase/shells/shells.cxx
+++ b/sw/qa/uibase/shells/shells.cxx
@@ -13,6 +13,9 @@
 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
 #include <com/sun/star/text/BibliographyDataType.hpp>
 #include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart/XChartDataArray.hpp>
 
 #include <sfx2/dispatch.hxx>
 #include <sfx2/viewfrm.hxx>
@@ -41,6 +44,8 @@
 #include <ndtxt.hxx>
 #include <ftnidx.hxx>
 #include <txtftn.hxx>
+#include <unotxdoc.hxx>
+#include <tools/json_writer.hxx>
 
 /// Covers sw/source/uibase/shells/ fixes.
 class SwUibaseShellsTest : public SwModelTestBase
@@ -587,6 +592,197 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, 
testInsertFieldmarkReadonly)
     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), nActual);
 }
 
+CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureTransformChart)
+{
+    createSwDoc("docStructureChartExampleOriginal.odt");
+    OString aJson = R"json(
+{
+    "Transforms": {
+        "Charts.ByEmbedIndex.0": {
+            "modifyrow.1": [ 19, 15 ],
+            "datayx.3.1": 37,
+            "deleterow.0": "",
+            "deleterow.1": "",
+            "insertrow.0": [ 15, 17 ],
+            "setrowdesc.0": "Paul",
+            "insertrow.2": [ 19, 22 ],
+            "setrowdesc.2": "Barbara",
+            "insertrow.4": [ 29, 27 ],
+            "setrowdesc.4": "Elizabeth",
+            "insertrow.5": [ 14, 26 ],
+            "setrowdesc.5": "William",
+            "insertcolumn.1": [ 1,2,3,4,5,6 ],
+            "insertcolumn.0": [ 2,1,2,1,2,1 ],
+            "insertcolumn.4": [ 7,7,7,7,7,7 ],
+            "setcolumndesc.4": "c4",
+            "setcolumndesc.0": "c0",
+            "setcolumndesc.2": "c2"
+        },
+        "Charts.BySubTitle.Subtitle2": {
+            "deletecolumn.3": ""
+        },
+        "Charts.ByEmbedName.Object3": {
+            "resize": [ 12, 3 ],
+            "setrowdesc":
+            [
+                "United Kingdom",
+                "United States of America",
+                "Canada",
+                "Brazil",
+                "Germany",
+                "India",
+                "Japan",
+                "Sudan",
+                "Norway",
+                "Italy",
+                "France",
+                "Egypt"
+            ],
+            "modifycolumn.0": [ 12, 9, 8, 5, 5, 4, 3, 3, 2, 2, 1, 1],
+            "resize": [ 12, 2 ]
+        },
+        "Charts.ByTitle.Fixed issues": {
+            "data": [ [ 3,1,2 ],
+                      [ 2,0,1 ],
+                      [ 3,2,0 ],
+                      [ 2,1,1 ],
+                      [ 4,2,2 ],
+                      [ 2,2,1 ],
+                      [ 3,2,0,0 ],
+                      [ 3,1,2,1 ],
+                      [ 3,3,1,0,1 ],
+                      [ 2,1,0,1,2 ],
+                      [ 4,2,1,2,2,3 ],
+                      [ 2,1,0,0,1,4 ],
+                      [ 3,2,2,1,3,2 ],
+                      [ 4,2,1,1,2,3 ],
+                      [ 3,3,2,0,3,5 ],
+                      [ 3,3,1,2,2,3 ],
+                      [ 5,1,1,1,1,4 ],
+                      [ 2,2,2,1,2,3 ] ],
+            "setrowdesc": 
["2023.01",".02",".03",".04",".05",".06",".07",".08",".09",".10",".11",".12","2023.01",".02",".03",".04",".05",".06"],
+            "setcolumndesc": ["Jennifer", "Charles", "Thomas", "Maria", 
"Lisa", "Daniel"]
+        }
+    }
+}
+)json"_ostr;
+
+    //transform
+    uno::Sequence<css::beans::PropertyValue> aArgs = {
+        comphelper::makePropertyValue(u"DataJson"_ustr,
+                                      uno::Any(OStringToOUString(aJson, 
RTL_TEXTENCODING_UTF8))),
+    };
+    dispatchCommand(mxComponent, u".uno:TransformDocumentStructure"_ustr, 
aArgs);
+
+    // Check transformed values of the 3 chart
+    for (int nShape = 0; nShape < 3; nShape++)
+    {
+        uno::Reference<text::XTextEmbeddedObjectsSupplier> xEOS(mxComponent, 
uno::UNO_QUERY);
+        CPPUNIT_ASSERT(xEOS.is());
+        uno::Reference<container::XIndexAccess> 
xEmbeddeds(xEOS->getEmbeddedObjects(),
+                                                           uno::UNO_QUERY);
+        CPPUNIT_ASSERT(xEmbeddeds.is());
+
+        uno::Reference<beans::XPropertySet> 
xShapeProps(xEmbeddeds->getByIndex(nShape),
+                                                        uno::UNO_QUERY);
+        CPPUNIT_ASSERT(xShapeProps.is());
+
+        uno::Reference<frame::XModel> xDocModel;
+        xShapeProps->getPropertyValue(u"Model"_ustr) >>= xDocModel;
+        CPPUNIT_ASSERT(xDocModel.is());
+
+        uno::Reference<chart2::XChartDocument> xChartDoc(xDocModel, 
uno::UNO_QUERY);
+        CPPUNIT_ASSERT(xChartDoc.is());
+
+        uno::Reference<chart::XChartDataArray> 
xDataArray(xChartDoc->getDataProvider(),
+                                                          uno::UNO_QUERY);
+        CPPUNIT_ASSERT(xDataArray.is());
+
+        switch (nShape)
+        {
+            case 0:
+            {
+                std::vector<std::vector<double>> aValues = {
+                    { 2, 15, 1, 7 }, { 1, 19, 2, 7 }, { 2, 19, 3, 7 },
+                    { 1, 25, 4, 7 }, { 2, 29, 5, 7 }, { 1, 14, 6, 7 },
+                };
+                // RowDescriptions
+                std::vector<OUString> aRowDescsValues
+                    = { u"Paul"_ustr,  u"Mary"_ustr,      u"Barbara"_ustr,
+                        u"David"_ustr, u"Elizabeth"_ustr, u"William"_ustr };
+                // ColumnDescriptions
+                std::vector<OUString> aColDescsValues
+                    = { u"c0"_ustr, u"2022"_ustr, u"c2"_ustr, u"c4"_ustr };
+
+                uno::Sequence<uno::Sequence<double>> aData = 
xDataArray->getData();
+                for (size_t nY = 0; nY < aValues.size(); nY++)
+                {
+                    for (size_t nX = 0; nX < aValues[nY].size(); nX++)
+                    {
+                        CPPUNIT_ASSERT_EQUAL(aData[nY][nX], aValues[nY][nX]);
+                    }
+                }
+
+                uno::Sequence<OUString> aColDescs = 
xDataArray->getColumnDescriptions();
+                for (size_t i = 0; i < aColDescsValues.size(); i++)
+                {
+                    CPPUNIT_ASSERT_EQUAL(aColDescs[i], aColDescsValues[i]);
+                }
+                uno::Sequence<OUString> aRowDescs = 
xDataArray->getRowDescriptions();
+                for (size_t i = 0; i < aRowDescsValues.size(); i++)
+                {
+                    CPPUNIT_ASSERT_EQUAL(aRowDescs[i], aRowDescsValues[i]);
+                }
+            }
+            break;
+            case 1:
+            {
+                uno::Sequence<uno::Sequence<double>> aData = 
xDataArray->getData();
+                CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(18), 
aData.getLength());
+                uno::Sequence<double>* pRows = aData.getArray();
+                CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(6), 
pRows[0].getLength());
+            }
+            break;
+            case 2:
+            {
+                uno::Sequence<uno::Sequence<double>> aData = 
xDataArray->getData();
+                CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(12), 
aData.getLength());
+                uno::Sequence<double>* pRows = aData.getArray();
+                CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), 
pRows[0].getLength());
+            }
+            break;
+            default:
+                break;
+        }
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureExtractChart)
+{
+    createSwDoc("docStructureChartExampleOriginal.odt");
+
+    //extract
+    tools::JsonWriter aJsonWriter;
+    std::string_view aCommand(".uno:ExtractDocumentStructure");
+    auto pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    pXTextDocument->getCommandValues(aJsonWriter, aCommand);
+
+    OString aExpectedStr
+        = "{ \"DocStructure\": { \"Charts.ByEmbedIndex.0\": { \"name\": 
\"Object1\", \"title\": "
+          "\"Paid leave days\", \"subtitle\": \"Subtitle2\", 
\"RowDescriptions\": [ \"James\", "
+          "\"Mary\", \"Patricia\", \"David\"], \"ColumnDescriptions\": [ 
\"2022\", \"2023\"], "
+          "\"DataValues\": [ \"Row.0\": [ \"22\", \"24\"], \"Row.1\": [ 
\"18\", \"16\"], "
+          "\"Row.2\": [ \"32\", \"32\"], \"Row.3\": [ \"25\", \"23\"]]}, "
+          "\"Charts.ByEmbedIndex.1\": { \"name\": \"Object2\", \"title\": 
\"Fixed issues\", "
+          "\"subtitle\": \"Subtitle1\", \"RowDescriptions\": [ \"\"], 
\"ColumnDescriptions\": [ \" "
+          "\"], \"DataValues\": [ \"Row.0\": [ \"NaN\"]]}, 
\"Charts.ByEmbedIndex.2\": { \"name\": "
+          "\"Object3\", \"title\": \"Employees from countries\", \"subtitle\": 
\"Subtitle3\", "
+          "\"RowDescriptions\": [ \"\"], \"ColumnDescriptions\": [ \"Column 
1\"], \"DataValues\": "
+          "[ \"Row.0\": [ \"NaN\"]]}}}"_ostr;
+
+    CPPUNIT_ASSERT_EQUAL(aExpectedStr, aJsonWriter.finishAndGetAsOString());
+}
+
 CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testUpdateRefmarks)
 {
     // Given a document with two refmarks, one is not interesting the other is 
a citation:
diff --git a/sw/source/uibase/shells/textsh1.cxx 
b/sw/source/uibase/shells/textsh1.cxx
index ed93f3b14a0a..4d767b5da8a3 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -130,6 +130,28 @@
 #include <formatcontentcontrol.hxx>
 #include <rtl/uri.hxx>
 
+#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
+#include <com/sun/star/chart2/XInternalDataProvider.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/chart/XChartDataArray.hpp>
+#include <com/sun/star/chart2/XTitle.hpp>
+#include <com/sun/star/chart2/XTitled.hpp>
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+
+#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
+#include <com/sun/star/chart2/XChartTypeContainer.hpp>
+#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+
+#include <com/sun/star/chart/ChartDataRowSource.hpp>
+#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
+#include <com/sun/star/chart2/XChartTypeContainer.hpp>
+#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
+//#include <../../../../chart2/source/controller/inc/ChartController.hxx>
+//#include <DataSeries.hxx>
+
 using namespace ::com::sun::star;
 using namespace com::sun::star::beans;
 using namespace ::com::sun::star::container;
@@ -784,6 +806,109 @@ void DeleteFields(SfxRequest& rReq, SwWrtShell& rWrtSh)
         pDoc->DeleteFormatRefMark(pMark);
     }
 }
+
+bool lcl_ChangeChartColumnCount(const uno::Reference<chart2::XChartDocument>& 
xChartDoc, sal_Int32 nId,
+                                bool bInsert, bool bResize = false)
+{
+    uno::Reference<chart2::XDiagram> xDiagram = xChartDoc->getFirstDiagram();
+    if (!xDiagram.is())
+        return false;
+    uno::Reference<chart2::XCoordinateSystemContainer> 
xCooSysContainer(xDiagram, uno::UNO_QUERY);
+    if (!xCooSysContainer.is())
+        return false;
+    uno::Sequence<uno::Reference<chart2::XCoordinateSystem>> xCooSysSequence(
+        xCooSysContainer->getCoordinateSystems());
+    if (xCooSysSequence.getLength() <= 0)
+        return false;
+    uno::Reference<chart2::XChartTypeContainer> 
xChartTypeContainer(xCooSysSequence[0],
+                                                                    
uno::UNO_QUERY);
+    if (!xChartTypeContainer.is())
+        return false;
+    uno::Sequence<uno::Reference<chart2::XChartType>> xChartTypeSequence(
+        xChartTypeContainer->getChartTypes());
+    if (xChartTypeSequence.getLength() <= 0)
+        return false;
+    uno::Reference<chart2::XDataSeriesContainer> 
xDSContainer(xChartTypeSequence[0],
+                                                              uno::UNO_QUERY);
+    if (!xDSContainer.is())
+        return false;
+
+    uno::Reference<chart2::XInternalDataProvider> 
xIDataProvider(xChartDoc->getDataProvider(),
+                                                                 
uno::UNO_QUERY);
+    if (!xIDataProvider.is())
+        return false;
+
+    uno::Sequence<uno::Reference<chart2::XDataSeries>> 
aSeriesSeq(xDSContainer->getDataSeries());
+
+    int nSeriesCount = aSeriesSeq.getLength();
+
+    if (bResize)
+    {
+        // Resize is actually some inserts, or deletes
+        if (nId > nSeriesCount)
+        {
+            bInsert = true;
+        }
+        else if (nId < nSeriesCount)
+        {
+            bInsert = false;
+        }
+        else
+        {
+            // Resize to the same size. No change needed
+            return true;
+        }
+    }
+
+    // insert or delete
+    if (bInsert)
+    {
+        // insert
+        if (nId > nSeriesCount && !bResize)
+            return false;
+
+        int nInsertCount = bResize ? nId - nSeriesCount : 1;
+
+        // call dialog code
+        if (bResize)
+        {
+            for (int i = 0; i < nInsertCount; i++)
+            {
+                xIDataProvider->insertDataSeries(nSeriesCount);
+            }
+            return true;
+        }
+
+        xIDataProvider->insertDataSeries(nId);
+    }
+    else
+    {
+        // delete 1 or more columns
+        if (nId >= nSeriesCount)
+            return false;
+        int nDeleteCount = bResize ? nSeriesCount - nId : 1;
+        for (int i = 0; i < nDeleteCount; i++)
+        {
+            xDSContainer->removeDataSeries(aSeriesSeq[nId]);
+        }
+    }
+    return true;
+}
+
+bool lcl_ResizeChartColumns(const uno::Reference<chart2::XChartDocument>& 
xChartDoc, sal_Int32 nSize)
+{
+    return lcl_ChangeChartColumnCount(xChartDoc, nSize, false, true);
+}
+
+bool lcl_InsertChartColumns(const uno::Reference<chart2::XChartDocument>& 
xChartDoc, sal_Int32 nId)
+{
+    return lcl_ChangeChartColumnCount(xChartDoc, nId, true);
+}
+
+bool lcl_DeleteChartColumns(const uno::Reference<chart2::XChartDocument>& 
xChartDoc, sal_Int32 nId)
+{
+    return lcl_ChangeChartColumnCount(xChartDoc, nId, false);
+}
 }
 
 void SwTextShell::Execute(SfxRequest &rReq)
@@ -2165,6 +2290,7 @@ void SwTextShell::Execute(SfxRequest &rReq)
             std::stringstream aStream(
                 (std::string(OUStringToOString(aDataJson, 
RTL_TEXTENCODING_UTF8))));
             boost::property_tree::read_json(aStream, aTree);
+            // Todo: try catch - in case of fail: log wrong JSON format
 
             // get the loaded content controls
             uno::Reference<text::XContentControlsSupplier> xCCSupplier(
@@ -2186,7 +2312,30 @@ void SwTextShell::Execute(SfxRequest &rReq)
             };
             std::vector<std::string> aIdTexts = { ".ByIndex.", ".ByTag.", 
".ByAlias.", ".ById." };
 
-            // Iterate trough the JSON data loaded into a tree structure
+            // get charts
+            uno::Reference<text::XTextEmbeddedObjectsSupplier> xEOS(
+                GetView().GetDocShell()->GetModel(), uno::UNO_QUERY);
+            if (!xEOS.is())
+                break;
+            uno::Reference<container::XIndexAccess> 
xEmbeddeds(xEOS->getEmbeddedObjects(),
+                                                               uno::UNO_QUERY);
+            if (!xEmbeddeds.is())
+                break;
+
+            sal_Int32 nEOcount = xEmbeddeds->getCount();
+
+            enum class ChartFilterType
+            {
+                ERROR = -1,
+                INDEX,
+                NAME,
+                TITLE,
+                SUBTITLE
+            };
+            std::vector<std::string> aIdChartTexts
+                = { ".ByEmbedIndex.", ".ByEmbedName.", ".ByTitle.", 
".BySubTitle." };
+
+            // Iterate through the JSON data loaded into a tree structure
             for (const auto& aItem : aTree)
             {
                 if (aItem.first == "Transforms")
@@ -2194,6 +2343,431 @@ void SwTextShell::Execute(SfxRequest &rReq)
                     // Handle all transformations
                     for (const auto& aItem2 : aItem.second)
                     {
+                        if (aItem2.first.starts_with("Charts"))
+                        {
+                            std::string aTextEnd = aItem2.first.substr(6);
+                            std::string aValue = "";
+                            ChartFilterType iKeyId = ChartFilterType::ERROR;
+                            // Find how the chart is identified: ByIndex, 
ByTitle...
+                            for (size_t i = 0; i < aIdChartTexts.size(); i++)
+                            {
+                                if (aTextEnd.starts_with(aIdChartTexts[i]))
+                                {
+                                    iKeyId = static_cast<ChartFilterType>(i);
+                                    aValue = 
aTextEnd.substr(aIdChartTexts[i].length());
+                                    break;
+                                }
+                            }
+                            if (iKeyId != ChartFilterType::ERROR)
+                            {
+                                for (int i = 0; i < nEOcount; ++i)
+                                {
+                                    uno::Reference<beans::XPropertySet> 
xShapeProps(
+                                        xEmbeddeds->getByIndex(i), 
uno::UNO_QUERY);
+                                    if (!xShapeProps.is())
+                                        continue;
+
+                                    uno::Reference<frame::XModel> xDocModel;
+                                    
xShapeProps->getPropertyValue(u"Model"_ustr) >>= xDocModel;
+                                    if (!xDocModel.is())
+                                        continue;
+
+                                    uno::Reference<chart2::XChartDocument> 
xChartDoc(
+                                        xDocModel, uno::UNO_QUERY);
+                                    if (!xChartDoc.is())
+                                        continue;
+
+                                    
uno::Reference<chart2::data::XDataProvider> xDataProvider(
+                                        xChartDoc->getDataProvider());
+                                    if (!xDataProvider.is())
+                                        continue;
+
+                                    uno::Reference<chart::XChartDataArray> 
xDataArray(
+                                        xChartDoc->getDataProvider(), 
uno::UNO_QUERY);
+                                    if (!xDataArray.is())
+                                        continue;
+
+                                    
uno::Reference<chart2::XInternalDataProvider> xIDataProvider(
+                                        xChartDoc->getDataProvider(), 
uno::UNO_QUERY);
+                                    if (!xIDataProvider.is())
+                                        continue;
+
+                                    uno::Reference<util::XModifiable> 
xModi(xDocModel,
+                                                                            
uno::UNO_QUERY);
+                                    if (!xModi.is())
+                                        continue;
+
+                                    switch (iKeyId)
+                                    {
+                                        case ChartFilterType::INDEX:
+                                        {
+                                            if (stoi(aValue) != i)
+                                                continue;
+                                        }
+                                        break;
+                                        case ChartFilterType::NAME:
+                                        {
+                                            uno::Reference<container::XNamed> 
xNamedShape(
+                                                xEmbeddeds->getByIndex(i), 
uno::UNO_QUERY);
+                                            if (xNamedShape.is())
+                                            {
+                                                OUString aName;
+                                                aName = xNamedShape->getName();
+                                                if (OStringToOUString(aValue, 
RTL_TEXTENCODING_UTF8)
+                                                    != aName)
+                                                    continue;
+                                            }
+                                        }
+                                        break;
+                                        case ChartFilterType::TITLE:
+                                        {
+                                            uno::Reference<chart2::XTitled> 
xTitled(
+                                                xChartDoc, 
uno::UNO_QUERY_THROW);
+                                            if (!xTitled.is())
+                                                continue;
+                                            uno::Reference<chart2::XTitle> 
xTitle
+                                                = xTitled->getTitleObject();
+                                            if (!xTitle.is())
+                                                continue;
+
+                                            OUString aTitle;
+                                            const uno::Sequence<
+                                                
uno::Reference<chart2::XFormattedString>>
+                                                aFSSeq = xTitle->getText();
+                                            for (auto const& fs : aFSSeq)
+                                                aTitle += fs->getString();
+                                            if (OStringToOUString(aValue, 
RTL_TEXTENCODING_UTF8)
+                                                != aTitle)
+                                                continue;
+                                        }
+                                        break;
+                                        case ChartFilterType::SUBTITLE:
+                                        {
+                                            uno::Reference<chart2::XDiagram> 
xDiagram
+                                                = xChartDoc->getFirstDiagram();
+                                            if (!xDiagram.is())
+                                                continue;
+
+                                            uno::Reference<chart2::XTitled> 
xTitled(
+                                                xDiagram, 
uno::UNO_QUERY_THROW);
+                                            if (!xTitled.is())
+                                                continue;
+
+                                            uno::Reference<chart2::XTitle> 
xSubTitle(
+                                                xTitled->getTitleObject());
+                                            if (!xSubTitle.is())
+                                                continue;
+
+                                            OUString aSubTitle;
+                                            const uno::Sequence<
+                                                
uno::Reference<chart2::XFormattedString>>
+                                                aFSSeq = xSubTitle->getText();
+                                            for (auto const& fs : aFSSeq)
+                                                aSubTitle += fs->getString();
+                                            if (OStringToOUString(aValue, 
RTL_TEXTENCODING_UTF8)
+                                                != aSubTitle)
+                                                continue;
+                                        }
+                                        break;
+                                        default:
+                                            continue;
+                                    }
+
+                                    // We have a match, this chart need to be 
transformed
+                                    // Set all the values (of the chart) what 
is needed
+
+                                    // Check if the InternalDataProvider is 
row or column based.
+                                    bool bChartUseColumns = false;
+                                    uno::Sequence<beans::PropertyValue> 
aArguments(
+                                        
xDataProvider->detectArguments(nullptr));
+                                    for (sal_Int32 j = 0; j < 
aArguments.getLength(); ++j)
+                                    {
+                                        if (aArguments[j].Name == 
"DataRowSource")
+                                        {
+                                            css::chart::ChartDataRowSource 
eRowSource;
+                                            if (aArguments[j].Value >>= 
eRowSource)
+                                                bChartUseColumns
+                                                    = (eRowSource
+                                                       == 
css::chart::ChartDataRowSource_COLUMNS);
+                                            break;
+                                        }
+                                    }
+
+                                    for (const auto& aItem3 : aItem2.second)
+                                    {
+                                        if 
(aItem3.first.starts_with("deletecolumn.")
+                                            || 
aItem3.first.starts_with("deleterow.")
+                                            || 
aItem3.first.starts_with("insertcolumn.")
+                                            || 
aItem3.first.starts_with("insertrow.")
+                                            || 
aItem3.first.starts_with("modifycolumn.")
+                                            || 
aItem3.first.starts_with("modifyrow."))
+                                        {
+                                            // delete insert, or modify a row, 
or column
+                                            // column, or row?
+                                            bool bSetColumn = (aItem3.first[6] 
== 'c');
+                                            int nId = 
stoi(aItem3.first.substr(bSetColumn ? 13 : 10));
+                                            bool bDelete = 
aItem3.first.starts_with("delete");
+                                            // delete/insert a row/column if 
needed
+                                            if 
(!aItem3.first.starts_with("modify"))
+                                            {
+                                                if (bChartUseColumns == 
bSetColumn)
+                                                {
+                                                    if (bDelete)
+                                                    {
+                                                        if 
(!lcl_DeleteChartColumns(xChartDoc, nId))
+                                                            continue;
+                                                        
xIDataProvider->deleteSequence(nId);
+                                                    }
+                                                    else
+                                                    {
+                                                        if 
(!lcl_InsertChartColumns(xChartDoc, nId))
+                                                            continue;
+                                                    }
+                                                }
+                                                else
+                                                {
+                                                    if (bDelete)
+                                                    {
+                                                        xIDataProvider
+                                                            
->deleteDataPointForAllSequences(nId);
+                                                    }
+                                                    else
+                                                    {
+                                                        xIDataProvider
+                                                            
->insertDataPointForAllSequences(nId
+                                                                               
              - 1);
+                                                    }
+                                                }
+                                            }
+                                            // set values also, if needed
+                                            if (!bDelete && 
aItem3.second.size() > 0)
+                                            {
+                                                
uno::Sequence<uno::Sequence<double>> aData
+                                                    = xDataArray->getData();
+                                                uno::Sequence<double>* pRows = 
aData.getArray();
+
+                                                int nIndex = 0;
+                                                int nX = nId;
+                                                int nY = nId;
+                                                for (const auto& aItem4 : 
aItem3.second)
+                                                {
+                                                    if (bSetColumn)
+                                                    {
+                                                        nY = nIndex;
+                                                    }
+                                                    else
+                                                    {
+                                                        nX = nIndex;
+                                                    }
+                                                    if (nY < aData.getLength() 
&& nY >= 0
+                                                        && nX < 
pRows[nY].getLength() && nX >= 0)
+                                                    {
+                                                        double* pCols = 
pRows[nY].getArray();
+                                                        pCols[nX]
+                                                            = 
aItem4.second.get_value<double>();
+                                                    }
+                                                    // else log: set invalid 
cell: index [nY,Nx]
+                                                    nIndex++;
+                                                }
+
+                                                xDataArray->setData(aData);
+                                            }
+                                        }
+                                        else if 
(aItem3.first.starts_with("setrowdesc"))
+                                        {
+                                            // set row descriptions
+                                            uno::Sequence<OUString> aRowDesc
+                                                = 
xDataArray->getRowDescriptions();
+                                            OUString* aRowdata = 
aRowDesc.getArray();
+
+                                            if 
(aItem3.first.starts_with("setrowdesc."))
+                                            {
+                                                // set only 1 description
+                                                int nValue = 
stoi(aItem3.first.substr(11));
+                                                if (nValue >= 0 && nValue < 
aRowDesc.getLength())
+                                                {
+                                                    aRowdata[nValue] = 
OStringToOUString(
+                                                        
aItem3.second.get_value<std::string>(),
+                                                        RTL_TEXTENCODING_UTF8);
+                                                }
+                                                // Todo: else log: wrong index 
at setcolumndesc.
+                                            }
+                                            else
+                                            {
+                                                // set an array of description 
at once
+                                                int nIndex = 0;
+                                                for (const auto& aItem4 : 
aItem3.second)
+                                                {
+                                                    if (nIndex >= 
aRowDesc.getLength())
+                                                    {
+                                                        // Todo log: too many 
parameters
+                                                        break;
+                                                    }
+                                                    aRowdata[nIndex] = 
OStringToOUString(
+                                                        
aItem4.second.get_value<std::string>(),
+                                                        RTL_TEXTENCODING_UTF8);
+                                                    nIndex++;
+                                                }
+                                            }
+                                            
xDataArray->setRowDescriptions(aRowDesc);
+                                        }
+                                        else if 
(aItem3.first.starts_with("setcolumndesc"))
+                                        {
+                                            // set colimn descriptions
+                                            uno::Sequence<OUString> aColDesc
+                                                = 
xDataArray->getColumnDescriptions();
+                                            OUString* aColdata = 
aColDesc.getArray();
+
+                                            if 
(aItem3.first.starts_with("setcolumndesc."))
+                                            {
+                                                int nValue = 
stoi(aItem3.first.substr(14));
+                                                if (nValue >= 0 && nValue < 
aColDesc.getLength())
+                                                {
+                                                    aColdata[nValue] = 
OStringToOUString(
+                                                        
aItem3.second.get_value<std::string>(),
+                                                        RTL_TEXTENCODING_UTF8);
+                                                }
+                                                // Todo: else log: wrong index 
at setcolumndesc.
+                                            }
+                                            else
+                                            {
+                                                int nIndex = 0;
+                                                for (const auto& aItem4 : 
aItem3.second)
+                                                {
+                                                    if (nIndex >= 
aColDesc.getLength())
+                                                    {
+                                                        // Todo log: too many 
parameters
+                                                        break;
+                                                    }
+                                                    aColdata[nIndex] = 
OStringToOUString(
+                                                        
aItem4.second.get_value<std::string>(),
+                                                        RTL_TEXTENCODING_UTF8);
+                                                    nIndex++;
+                                                }
+                                            }
+                                            
xDataArray->setColumnDescriptions(aColDesc);
+                                        }
+                                        else if 
(aItem3.first.starts_with("resize"))
+                                        {
+                                            if (aItem3.second.size() >= 2)
+                                            {
+                                                auto aItem4 = 
aItem3.second.begin();
+                                                int nY = 
aItem4->second.get_value<int>();
+                                                int nX = 
(++aItem4)->second.get_value<int>();
+
+                                                if (nX < 1 || nY < 1)
+                                                {
+                                                    // Todo log: wrong resize 
argument
+                                                    continue;
+                                                }
+                                                // here we need to use the new 
insert column thing
+                                                if 
(!lcl_ResizeChartColumns(xChartDoc, nX))
+                                                    continue;
+
+                                                
uno::Sequence<uno::Sequence<double>> aData
+                                                    = xDataArray->getData();
+                                                if (aData.getLength() != nY)
+                                                    aData.realloc(nY);
+
+                                                for (sal_Int32 j = 0; j < nY; 
++j)
+                                                {
+                                                    uno::Sequence<double>* 
pRows = aData.getArray();
+                                                    // resize row if needed
+                                                    if (pRows[j].getLength() 
!= nX)
+                                                    {
+                                                        pRows[j].realloc(nX);
+                                                    }
+                                                }
+                                                xDataArray->setData(aData);
+                                            }
+                                            // Todo: else log: not enought 
parameter for resize
+                                        }
+                                        else if 
(aItem3.first.starts_with("data"))
+                                        {
+                                            // set table data values
+                                            
uno::Sequence<uno::Sequence<double>> aData
+                                                = xDataArray->getData();
+
+                                            // set only 1 cell data
+                                            if 
(aItem3.first.starts_with("datayx."))
+                                            {
+                                                int nPoint = 
aItem3.first.find('.', 7);
+                                                int nY = 
stoi(aItem3.first.substr(7, nPoint - 7));
+                                                int nX = 
stoi(aItem3.first.substr(nPoint + 1));
+                                                if (nY < aData.getLength() && 
nY >= 0)
+                                                {
+                                                    uno::Sequence<double>* 
pRows = aData.getArray();
+                                                    if (nX < 
pRows[nY].getLength() && nX >= 0)
+                                                    {
+                                                        double* pCols = 
pRows[nY].getArray();
+                                                        pCols[nX]
+                                                            = 
aItem3.second.get_value<double>();
+                                                    }
+                                                }
+                                            }
+                                            else
+                                            {
+                                                // set the whole data table
+                                                // resize if needed
+                                                int nRowsCount = 
aItem3.second.size();
+                                                int nColsCount = 0;
+
+                                                for (const auto& aItem4 : 
aItem3.second)
+                                                {
+                                                    if (nColsCount
+                                                        < 
static_cast<int>(aItem4.second.size()))
+                                                    {
+                                                        nColsCount = 
aItem4.second.size();
+                                                    }
+                                                }
+
+                                                if (nColsCount > 0)
+                                                {
+                                                    // here we need to use the 
new insert column thing
+                                                    
if(!lcl_ResizeChartColumns(xChartDoc, nColsCount))
+                                                        continue;
+
+                                                    if (aData.getLength() != 
nRowsCount)
+                                                        
aData.realloc(nRowsCount);
+
+                                                    // set all the rows
+                                                    sal_Int32 nY = 0;
+                                                    for (const auto& aItem4 : 
aItem3.second)
+                                                    {
+                                                        uno::Sequence<double>* 
pRows
+                                                            = aData.getArray();
+                                                        // resize row if needed
+                                                        if 
(pRows[nY].getLength() != nColsCount)
+                                                        {
+                                                            
pRows[nY].realloc(nColsCount);
+                                                        }
+                                                        double* pCols = 
pRows[nY].getArray();
+                                                        // set all values in 
the row
+                                                        sal_Int32 nX = 0;
+                                                        for (const auto& 
aItem5 : aItem4.second)
+                                                        {
+                                                            if (nX >= 
nColsCount)
+                                                            {
+                                                                break;
+                                                            }
+                                                            pCols[nX]
+                                                                = 
aItem5.second.get_value<double>();
+                                                            nX++;
+                                                        }
+                                                        nY++;
+                                                    }
+                                                }
+                                            }
+                                            xDataArray->setData(aData);
+                                        }
+                                        // Todo: else Log that this chart 
command was not recognised
+                                        xModi->setModified(true);
+                                    }
+                                }
+                            }
+                            // todo: else log chart transfrom not recognised
+                        }
+
                         if (aItem2.first.starts_with("ContentControls"))
                         {
                             std::string aTextEnd = aItem2.first.substr(15);
@@ -2372,6 +2946,15 @@ void SwTextShell::Execute(SfxRequest &rReq)
                                                 continue;
                                             
xContentControlText->setString(aCheckContent);
                                         }
+                                        else if (aItem3.first == "date")
+                                        {
+                                            std::string aDate
+                                                = 
aItem3.second.get_value<std::string>();
+                                            
xContentControlProps->setPropertyValue(
+                                                UNO_NAME_CURRENT_DATE,
+                                                
uno::Any(OStringToOUString(aDate,
+                                                                           
RTL_TEXTENCODING_UTF8)));
+                                        }
                                         else if (aItem3.first == "alias")
                                         {
                                             
xContentControlProps->setPropertyValue(
diff --git a/sw/source/uibase/uno/loktxdoc.cxx 
b/sw/source/uibase/uno/loktxdoc.cxx
index 2d76e6110cd6..2ae6edb96ece 100644
--- a/sw/source/uibase/uno/loktxdoc.cxx
+++ b/sw/source/uibase/uno/loktxdoc.cxx
@@ -44,6 +44,14 @@
 #include <unocontentcontrol.hxx>
 #include <com/sun/star/text/XTextContent.hpp>
 
+#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
+#include <com/sun/star/chart2/XInternalDataProvider.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart/XChartDocument.hpp>
+#include <com/sun/star/chart/XChartDataArray.hpp>
+#include <com/sun/star/chart2/XTitle.hpp>
+#include <com/sun/star/chart2/XTitled.hpp>
+
 using namespace ::com::sun::star;
 
 namespace
@@ -403,7 +411,6 @@ void GetDocStructure(tools::JsonWriter& rJsonWriter, 
SwDocShell* /*pDocShell*/,
 
     int iCCcount = xContentControls->getCount();
 
-    auto commentsNode = rJsonWriter.startNode("DocStructure");
     for (int i = 0; i < iCCcount; ++i)
     {
         OString aNodeName("ContentControls.ByIndex."_ostr + 
OString::number(i));
@@ -477,6 +484,9 @@ void GetDocStructure(tools::JsonWriter& rJsonWriter, 
SwDocShell* /*pDocShell*/,
                 OUString aDateLanguage;
                 xContentControlProps->getPropertyValue(UNO_NAME_DATE_LANGUAGE) 
>>= aDateLanguage;
                 rJsonWriter.put(UNO_NAME_DATE_LANGUAGE, aDateLanguage);
+                OUString aCurrentDate;
+                xContentControlProps->getPropertyValue(UNO_NAME_CURRENT_DATE) 
>>= aCurrentDate;
+                rJsonWriter.put(UNO_NAME_CURRENT_DATE, aCurrentDate);
             }
             break;
             case SwContentControlType::PLAIN_TEXT:
@@ -497,6 +507,125 @@ void GetDocStructure(tools::JsonWriter& rJsonWriter, 
SwDocShell* /*pDocShell*/,
     }
 }
 
+void GetDocStructureCharts(tools::JsonWriter& rJsonWriter, SwDocShell* 
/*pDocShell*/,
+                           const std::map<OUString, OUString>& rArguments,
+                           uno::Reference<container::XIndexAccess>& xEmbeddeds)
+{
+    auto it = rArguments.find(u"filter"_ustr);
+    if (it != rArguments.end())
+    {
+        // If filter is present but we are filtering not to charts
+        if (!it->second.equals(u"charts"_ustr))
+            return;
+    }
+
+    sal_Int32 nEOcount = xEmbeddeds->getCount();
+
+    for (int i = 0; i < nEOcount; ++i)
+    {
+        uno::Reference<beans::XPropertySet> 
xShapeProps(xEmbeddeds->getByIndex(i), uno::UNO_QUERY);
+        if (!xShapeProps.is())
+            continue;
+
+        uno::Reference<frame::XModel> xDocModel;
+        xShapeProps->getPropertyValue(u"Model"_ustr) >>= xDocModel;
+        if (!xDocModel.is())
+            continue;
+
+        uno::Reference<chart2::XChartDocument> xChartDoc(xDocModel, 
uno::UNO_QUERY);
+        if (!xChartDoc.is())
+            continue;
+
+        uno::Reference<chart2::data::XDataProvider> 
xDataProvider(xChartDoc->getDataProvider());
+        if (!xDataProvider.is())
+            continue;
+
+        uno::Reference<chart::XChartDataArray> 
xDataArray(xChartDoc->getDataProvider(),
+                                                          uno::UNO_QUERY);
+        if (!xDataArray.is())
+            continue;
+
+        uno::Reference<chart2::XDiagram> xDiagram = 
xChartDoc->getFirstDiagram();
+        if (!xDiagram.is())
+            continue;
+
+        //we have the chart Data now, we can start to extract it
+        OString aNodeName("Charts.ByEmbedIndex."_ostr + OString::number(i));
+        auto aChartNode = rJsonWriter.startNode(aNodeName);
+
+        //get the object name
+        uno::Reference<container::XNamed> 
xNamedShape(xEmbeddeds->getByIndex(i), uno::UNO_QUERY);
+        if (xNamedShape.is())
+        {
+            OUString aName;
+            aName = xNamedShape->getName();
+            rJsonWriter.put("name", aName);
+        }
+
+        //get the chart title, if there is one
+        uno::Reference<chart2::XTitled> xTitled(xChartDoc, 
uno::UNO_QUERY_THROW);
+        if (xTitled.is())
+        {
+            uno::Reference<chart2::XTitle> xTitle = xTitled->getTitleObject();
+            if (xTitle.is())
+            {
+                OUString aTitle;
+                const uno::Sequence<uno::Reference<chart2::XFormattedString>> 
aFSSeq
+                    = xTitle->getText();
+                for (auto const& fs : aFSSeq)
+                    aTitle += fs->getString();
+                rJsonWriter.put("title", aTitle);
+            }
+        }
+
+        //get the chart subtitle, if there is one
+        uno::Reference<chart2::XTitled> xSubTitled(xDiagram, 
uno::UNO_QUERY_THROW);
+        if (xSubTitled.is())
+        {
+            uno::Reference<chart2::XTitle> xSubTitle = 
xSubTitled->getTitleObject();
+            if (xSubTitle.is())
+            {
+                OUString aSubTitle;
+                const uno::Sequence<uno::Reference<chart2::XFormattedString>> 
aFSSeq
+                    = xSubTitle->getText();
+                for (auto const& fs : aFSSeq)
+                    aSubTitle += fs->getString();
+                rJsonWriter.put("subtitle", aSubTitle);
+            }
+        }
+
+        {
+            uno::Sequence<OUString> aRowDesc = 
xDataArray->getRowDescriptions();
+            auto aRowDescNode = rJsonWriter.startArray("RowDescriptions");
+            for (int j = 0; j < aRowDesc.getLength(); j++)
+            {
+                rJsonWriter.putSimpleValue(aRowDesc[j]);
+            }
+        }
+        {
+            uno::Sequence<OUString> aColDesc = 
xDataArray->getColumnDescriptions();
+            auto aColDescNode = rJsonWriter.startArray("ColumnDescriptions");
+            for (int j = 0; j < aColDesc.getLength(); j++)
+            {
+                rJsonWriter.putSimpleValue(aColDesc[j]);
+            }
+        }
+        {
+            uno::Sequence<uno::Sequence<double>> aData = xDataArray->getData();
+            auto aDataValuesNode = rJsonWriter.startArray("DataValues");
+            for (int j = 0; j < aData.getLength(); j++)
+            {
+                OString aRowNodeName("Row."_ostr + OString::number(j));
+                auto aRowNode = rJsonWriter.startArray(aRowNodeName);
+                for (int k = 0; k < aData[j].getLength(); k++)
+                {
+                    rJsonWriter.putSimpleValue(OUString::number(aData[j][k]));
+                }
+            }
+        }
+    }
+}
+
 /// Implements getCommandValues(".uno:Sections").
 ///
 /// Parameters:
@@ -609,6 +738,14 @@ void SwXTextDocument::getCommandValues(tools::JsonWriter& 
rJsonWriter, std::stri
     }
     else if (o3tl::starts_with(rCommand, aExtractDocStructure))
     {
+        auto commentsNode = rJsonWriter.startNode("DocStructure");
+
+        uno::Reference<container::XIndexAccess> 
xEmbeddeds(getEmbeddedObjects(), uno::UNO_QUERY);
+        if (xEmbeddeds.is())
+        {
+            GetDocStructureCharts(rJsonWriter, m_pDocShell, aMap, xEmbeddeds);
+        }
+
         uno::Reference<container::XIndexAccess> xContentControls = 
getContentControls();
         GetDocStructure(rJsonWriter, m_pDocShell, aMap, xContentControls);
     }

Reply via email to