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(std::string_view s, bool /*transient*/)
45 {
46 if (mnCol > mpDoc->MaxCol())
47 return;
48
49 double mfValue = 0.0;
50 if (ScStringUtil::parseSimpleNumber(s.data(), s.size(), '.', ',', mfValue))
51 {
52 mpDoc->SetValue(mnCol, mnRow, 0, mfValue);
53 }
54 else
55 {
56 mpDoc->SetString(mnCol, mnRow, 0, OStringToOUString(s, RTL_TEXTENCODING_UTF8));
57 }
58
59 ++mnCol;
60 }
61};
62
63}
64
65namespace sc {
67 ScDocument& rDoc, OUString aURL, std::function<void()> aImportFinishedHdl,
68 std::vector<std::shared_ptr<sc::DataTransformation>>&& rDataTransformations)
69 : Thread("CSV Fetch Thread")
70 , mrDocument(rDoc)
71 , maURL(std::move(aURL))
72 , mbTerminate(false)
73 , maDataTransformations(std::move(rDataTransformations))
74 , maImportFinishedHdl(std::move(aImportFinishedHdl))
75{
76 maConfig.delimiters.push_back(',');
77 maConfig.text_qualifier = '"';
78}
79
81{
82}
83
85{
86 return mbTerminate.load();
87}
88
90{
91 mbTerminate.store(true);
92}
93
95{
97}
98
100{
101 OStringBuffer aBuffer(64000);
103 if (mbTerminate)
104 return;
105
106 CSVHandler aHdl(&mrDocument);
107 orcus::csv_parser<CSVHandler> parser(aBuffer, aHdl, maConfig);
108 parser.parse();
109
110 for (const auto& itr : maDataTransformations)
111 {
112 itr->Transform(mrDocument);
113 }
114
115 SolarMutexGuard aGuard;
117}
118
120 DataProvider(rDataSource),
121 mpDocument(pDoc)
122{
123}
124
126{
127 if (mxCSVFetchThread.is())
128 {
129 SolarMutexReleaser aReleaser;
130 mxCSVFetchThread->join();
131 }
132}
133
135{
136 // already importing data
137 if (mpDoc)
138 return;
139
140 mpDoc.reset(new ScDocument(SCDOCMODE_CLIP));
141 mpDoc->ResetClip(mpDocument, SCTAB(0));
143 mxCSVFetchThread->launch();
144
145 if (mbDeterministic)
146 {
147 SolarMutexReleaser aReleaser;
148 mxCSVFetchThread->join();
149 }
150}
151
153{
155 mpDoc.reset();
156 Refresh();
157}
158
160{
161 ScDocShell* pDocShell = static_cast<ScDocShell*>(mpDocument->GetDocumentShell());
162 if (pDocShell)
163 pDocShell->SetDocumentModified();
164}
165
166const OUString& CSVDataProvider::GetURL() const
167{
168 return mrDataSource.getURL();
169}
170
171}
172
173/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetDocumentModified()
Definition: docsh.cxx:2982
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:892
SC_DLLPUBLIC bool SetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString &rString, const ScSetStringParam *pParam=nullptr)
Definition: document.cxx:3391
SC_DLLPUBLIC void SetValue(SCCOL nCol, SCROW nRow, SCTAB nTab, const double &rVal)
Definition: document.cxx:3477
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1083
static bool parseSimpleNumber(const OUString &rStr, sal_Unicode dsep, sal_Unicode gsep, sal_Unicode dsepa, double &rVal, bool bDetectScientificNumber=true)
Check if a given string is a simple decimal number (e.g.
Definition: stringutil.cxx:55
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
ScDocument & mrDocument
std::function< void()> maImportFinishedHdl
std::atomic< bool > mbTerminate
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:257
sal_Int32 mnRow
sal_Int32 mnCol
parser
CAUTION! The following defines must be in the same namespace as the respective type.
Definition: broadcast.cxx:15
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