Date: prev next · Thread: first prev next last
2011 Archives by date, by thread · List index


I'd like to backport the attached patch to the 3-4 branch.

Without this patch, import of charts in Excel documents fail when the
data series consist of multiple cell ranges, which is common in complex
chart objects.  The failure happens only in locales where the function
and range separator is ',' (Tools - Options - Calc - Formula -
Separators - Function), which is default in the English locales and
others.

I've attached a very small example document to demonstrate the failed
chart import, which is amazingly smaller than the patch itself when
compressed. ;-)

Anyway, review and sign-off very much appreciated.

Kohei

-- 
Kohei Yoshida, LibreOffice hacker, Calc
<kohei.yoshida@suse.com>
From 0e83658f97696e498ebbc616056fe1a4089ce321 Mon Sep 17 00:00:00 2001
From: Kohei Yoshida <kohei.yoshida@suse.com>
Date: Tue, 9 Aug 2011 15:49:15 -0400
Subject: [PATCH] Correctly import from Excel charts with multiple ranges.

This was "fixed" in i#107275, but the fix only worked in locales
where the range/argument separator was ';' (e.g. German locale).
This is the correct fix that works in all locales regardless of
the separator.
---
 sc/inc/reftokenhelper.hxx                     |    2 +-
 sc/source/core/tool/reftokenhelper.cxx        |    4 +-
 sc/source/filter/xml/XMLTableShapeResizer.cxx |    5 ++-
 sc/source/ui/unoobj/chart2uno.cxx             |   38 +++++++++++++++++--------
 4 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/sc/inc/reftokenhelper.hxx b/sc/inc/reftokenhelper.hxx
index 8451a16..3566fd7 100644
--- a/sc/inc/reftokenhelper.hxx
+++ b/sc/inc/reftokenhelper.hxx
@@ -55,7 +55,7 @@ public:
      */
     static void compileRangeRepresentation(
         ::std::vector<ScTokenRef>& rRefTokens, const ::rtl::OUString& rRangeStr, ScDocument* pDoc,
-        ::formula::FormulaGrammar::Grammar eGrammar = ::formula::FormulaGrammar::GRAM_ENGLISH);
+        const sal_Unicode cSep, ::formula::FormulaGrammar::Grammar eGrammar);
 
     static bool getRangeFromToken(ScRange& rRange, const ScTokenRef& pToken, bool bExternal = 
false);
 
diff --git a/sc/source/core/tool/reftokenhelper.cxx b/sc/source/core/tool/reftokenhelper.cxx
index e77f130..fb54280 100644
--- a/sc/source/core/tool/reftokenhelper.cxx
+++ b/sc/source/core/tool/reftokenhelper.cxx
@@ -47,9 +47,9 @@ using ::std::auto_ptr;
 using ::rtl::OUString;
 
 void ScRefTokenHelper::compileRangeRepresentation(
-    vector<ScTokenRef>& rRefTokens, const OUString& rRangeStr, ScDocument* pDoc, 
FormulaGrammar::Grammar eGrammar)
+    vector<ScTokenRef>& rRefTokens, const OUString& rRangeStr, ScDocument* pDoc,
+    const sal_Unicode cSep, FormulaGrammar::Grammar eGrammar)
 {
-    const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
     const sal_Unicode cQuote = '\'';
 
     // #i107275# ignore parentheses
diff --git a/sc/source/filter/xml/XMLTableShapeResizer.cxx 
b/sc/source/filter/xml/XMLTableShapeResizer.cxx
index e0425c0..6d61b80 100644
--- a/sc/source/filter/xml/XMLTableShapeResizer.cxx
+++ b/sc/source/filter/xml/XMLTableShapeResizer.cxx
@@ -35,6 +35,7 @@
 #include "chartlis.hxx"
 #include "XMLConverter.hxx"
 #include "rangeutl.hxx"
+#include "compiler.hxx"
 #include "reftokenhelper.hxx"
 #include <tools/debug.hxx>
 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
@@ -94,7 +95,9 @@ void ScMyOLEFixer::CreateChartListener(ScDocument* pDoc,
         return;
 
     auto_ptr< vector<ScTokenRef> > pRefTokens(new vector<ScTokenRef>);
-    ScRefTokenHelper::compileRangeRepresentation(*pRefTokens, aRangeStr, pDoc);
+    const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
+    ScRefTokenHelper::compileRangeRepresentation(
+        *pRefTokens, aRangeStr, pDoc, cSep, formula::FormulaGrammar::GRAM_ENGLISH);
     if (!pRefTokens->empty())
     {
         ScChartListener* pCL(new ScChartListener(rName, pDoc, pRefTokens.release()));
diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx
index 32fc54a..8c43501 100644
--- a/sc/source/ui/unoobj/chart2uno.cxx
+++ b/sc/source/ui/unoobj/chart2uno.cxx
@@ -1043,7 +1043,9 @@ void ScChart2DataProvider::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& 
rHint
     }
 
     vector<ScTokenRef> aTokens;
-    ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, 
m_pDocument->GetGrammar());
+    const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
+    ScRefTokenHelper::compileRangeRepresentation(
+        aTokens, aRangeRepresentation, m_pDocument, cSep, m_pDocument->GetGrammar());
     return !aTokens.empty();
 }
 
@@ -1419,7 +1421,9 @@ ScChart2DataProvider::createDataSource(
     }
 
     vector<ScTokenRef> aRefTokens;
-    ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, 
m_pDocument->GetGrammar());
+    const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
+    ScRefTokenHelper::compileRangeRepresentation(
+        aRefTokens, aRangeRepresentation, m_pDocument, cSep, m_pDocument->GetGrammar());
     if (aRefTokens.empty())
         // Invalid range representation.  Bail out.
         throw lang::IllegalArgumentException();
@@ -1743,7 +1747,9 @@ uno::Sequence< beans::PropertyValue > SAL_CALL 
ScChart2DataProvider::detectArgum
                 {
                     bFirstCellAsLabel = true;
                     vector<ScTokenRef> aTokens;
-                    ScRefTokenHelper::compileRangeRepresentation( aTokens, 
xLabel->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() );
+                    const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
+                    ScRefTokenHelper::compileRangeRepresentation(
+                        aTokens, xLabel->getSourceRangeRepresentation(), m_pDocument, cSep, 
m_pDocument->GetGrammar());
                     aLabel.initRangeAnalyzer(aTokens);
                     vector<ScTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = 
aTokens.end();
                     for (; itr != itrEnd; ++itr)
@@ -1760,7 +1766,9 @@ uno::Sequence< beans::PropertyValue > SAL_CALL 
ScChart2DataProvider::detectArgum
                 if( xValues.is())
                 {
                     vector<ScTokenRef> aTokens;
-                    ScRefTokenHelper::compileRangeRepresentation( aTokens, 
xValues->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() );
+                    const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
+                    ScRefTokenHelper::compileRangeRepresentation(
+                        aTokens, xValues->getSourceRangeRepresentation(), m_pDocument, cSep, 
m_pDocument->GetGrammar());
                     aValues.initRangeAnalyzer(aTokens);
                     vector<ScTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = 
aTokens.end();
                     for (; itr != itrEnd; ++itr)
@@ -1967,7 +1975,9 @@ uno::Sequence< beans::PropertyValue > SAL_CALL 
ScChart2DataProvider::detectArgum
         return false;
 
     vector<ScTokenRef> aTokens;
-    ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, 
m_pDocument->GetGrammar());
+    const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
+    ScRefTokenHelper::compileRangeRepresentation(
+        aTokens, aRangeRepresentation, m_pDocument, cSep, m_pDocument->GetGrammar());
     return !aTokens.empty();
 }
 
@@ -1984,14 +1994,16 @@ uno::Reference< chart2::data::XDataSequence > SAL_CALL
     if(!m_pDocument || (aRangeRepresentation.getLength() == 0))
         return xResult;
 
-    // Note: the range representation must be in Calc A1 format.  The import 
-    // filters use this method to pass data ranges, and they have no idea what
-    // the current formula syntax is.  In the future we should add another
-    // method to allow the client code to directly pass tokens representing
-    // ranges.
+    // Note: the range representation must be in Calc A1 format, with English
+    // function names and ';' as the union operator in case of multiple
+    // ranges. The import filters use this method to pass data ranges, and
+    // they have no idea what the current formula syntax is. In the future we
+    // should add another method to allow the client code to directly pass
+    // tokens representing ranges.
 
     vector<ScTokenRef> aRefTokens;
-    ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument);
+    ScRefTokenHelper::compileRangeRepresentation(
+        aRefTokens, aRangeRepresentation, m_pDocument, ';', FormulaGrammar::GRAM_ENGLISH);
     if (aRefTokens.empty())
         return xResult;
 
@@ -2029,7 +2041,9 @@ rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeToXML( const 
rtl::OUStr
         return aRet;
 
     vector<ScTokenRef> aRefTokens;
-    ScRefTokenHelper::compileRangeRepresentation(aRefTokens, sRangeRepresentation, m_pDocument, 
m_pDocument->GetGrammar());
+    const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
+    ScRefTokenHelper::compileRangeRepresentation(
+        aRefTokens, sRangeRepresentation, m_pDocument, cSep, m_pDocument->GetGrammar());
     if (aRefTokens.empty())
         throw lang::IllegalArgumentException();
 
-- 
1.7.3.4

Attachment: chart-series-disjoint.xls.gz
Description: GNU Zip compressed data


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.