LibreOffice Module sc (master) 1
csvdataprovider.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include <dataprovider.hxx>
12#include <datamapper.hxx>
13#include <stringutil.hxx>
14
15#include <tools/stream.hxx>
16#include <utility>
17#include <vcl/svapp.hxx>
18#include <docsh.hxx>
19#include <orcus/csv_parser.hpp>
20
21namespace {
22
23class CSVHandler
24{
25 ScDocument* mpDoc;
28
29public:
30 CSVHandler(ScDocument* pDoc) :
31 mpDoc(pDoc), mnCol(0), mnRow(0)
32 {
33 }
34
35 static void begin_parse() {}
36 static void end_parse() {}
37 static void begin_row() {}
38 void end_row()
39 {
40 ++mnRow;
41 mnCol = 0;
42 }
43
44 void cell(const char* p, size_t n, bool /*transient*/)
45 {
46 if (mnCol > mpDoc->MaxCol())
47 return;
48
49 double mfValue = 0.0;
50 if (ScStringUtil::parseSimpleNumber(p, n, '.', ',', mfValue))
51 {
52 mpDoc->SetValue(mnCol, mnRow, 0, mfValue);
53 }
54 else
55 {
56 OString aStr(p, n);
57 mpDoc->SetString(mnCol, mnRow, 0, OStringToOUString(aStr, RTL_TEXTENCODING_UTF8));
58 }
59
60 ++mnCol;
61 }
62};
63
64}
65
66namespace sc {
68 ScDocument& rDoc, OUString aURL, std::function<void()> aImportFinishedHdl,
69 std::vector<std::shared_ptr<sc::DataTransformation>>&& rDataTransformations)
70 : Thread("CSV Fetch Thread")
71 , mrDocument(rDoc)
72 , maURL(std::move(aURL))
73 , mbTerminate(false)
74 , maDataTransformations(std::move(rDataTransformations))
75 , maImportFinishedHdl(std::move(aImportFinishedHdl))
76{
77 maConfig.delimiters.push_back(',');
78 maConfig.text_qualifier = '"';
79}
80
82{
83}
84
86{
87 osl::MutexGuard aGuard(maMtxTerminate);
88 return mbTerminate;
89}
90
92{
93 osl::MutexGuard aGuard(maMtxTerminate);
94 mbTerminate = true;
95}
96
98{
100}
101
103{
104 OStringBuffer aBuffer(64000);
106 if (mbTerminate)
107 return;
108
109 CSVHandler aHdl(&mrDocument);
110 orcus::csv_parser<CSVHandler> parser(aBuffer.getStr(), aBuffer.getLength(), aHdl, maConfig);
111 parser.parse();
112
113 for (const auto& itr : maDataTransformations)
114 {
115 itr->Transform(mrDocument);
116 }
117
118 SolarMutexGuard aGuard;
120}
121
123 DataProvider(rDataSource),
124 mpDocument(pDoc)
125{
126}
127
129{
130 if (mxCSVFetchThread.is())
131 {
132 SolarMutexReleaser aReleaser;
133 mxCSVFetchThread->join();
134 }
135}
136
138{
139 // already importing data
140 if (mpDoc)
141 return;
142
143 mpDoc.reset(new ScDocument(SCDOCMODE_CLIP));
144 mpDoc->ResetClip(mpDocument, SCTAB(0));
146 mxCSVFetchThread->launch();
147
148 if (mbDeterministic)
149 {
150 SolarMutexReleaser aReleaser;
151 mxCSVFetchThread->join();
152 }
153}
154
156{
158 mpDoc.reset();
159 Refresh();
160}
161
163{
164 ScDocShell* pDocShell = static_cast<ScDocShell*>(mpDocument->GetDocumentShell());
165 if (pDocShell)
166 pDocShell->SetDocumentModified();
167}
168
169const OUString& CSVDataProvider::GetURL() const
170{
171 return mrDataSource.getURL();
172}
173
174}
175
176/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetDocumentModified()
Definition: docsh.cxx:2959
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:891
SC_DLLPUBLIC bool SetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString &rString, const ScSetStringParam *pParam=nullptr)
Definition: document.cxx:3422
SC_DLLPUBLIC void SetValue(SCCOL nCol, SCROW nRow, SCTAB nTab, const double &rVal)
Definition: document.cxx:3517
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1081
static bool parseSimpleNumber(const OUString &rStr, sal_Unicode dsep, sal_Unicode gsep, sal_Unicode dsepa, double &rVal)
Check if a given string is a simple decimal number (e.g.
Definition: stringutil.cxx:52
const OUString & GetURL() const override
rtl::Reference< CSVFetchThread > mxCSVFetchThread
virtual ~CSVDataProvider() override
virtual void Import() override
ScDocument * mpDocument
ScDocumentUniquePtr mpDoc
CSVDataProvider(ScDocument *pDoc, sc::ExternalDataSource &rDataSource)
CSVFetchThread(ScDocument &rDoc, OUString, std::function< void()> aImportFinishedHdl, std::vector< std::shared_ptr< sc::DataTransformation > > &&mrDataTransformations)
std::vector< std::shared_ptr< sc::DataTransformation > > maDataTransformations
osl::Mutex maMtxTerminate
ScDocument & mrDocument
std::function< void()> maImportFinishedHdl
orcus::csv::parser_config maConfig
virtual ~CSVFetchThread() override
virtual void execute() override
Abstract class for all data provider.
static std::unique_ptr< SvStream > FetchStreamFromURL(const OUString &, OStringBuffer &rBuffer)
bool mbDeterministic
If true make the threaded import deterministic for the tests.
sc::ExternalDataSource & mrDataSource
const std::vector< std::shared_ptr< sc::DataTransformation > > & getDataTransformation() const
const OUString & getURL() const
ScDBDataManager * getDBManager()
void WriteToDoc(ScDocument &rDoc)
URL aURL
@ SCDOCMODE_CLIP
Definition: document.hxx:256
sal_Int32 mnRow
sal_Int32 mnCol
aStr
parser
CAUTION! The following defines must be in the same namespace as the respective type.
const URL maURL
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17
std::unique_ptr< char[]> aBuffer