Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: XLS Translator
4 : * Purpose: Implements OGRXLSDataSource class
5 : * Author: Even Rouault, even dot rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2011, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "include_freexl.h"
30 :
31 : #ifdef _WIN32
32 : #include <windows.h>
33 : #endif
34 :
35 : #include "ogr_xls.h"
36 : #include "cpl_conv.h"
37 : #include "cpl_string.h"
38 :
39 : /************************************************************************/
40 : /* OGRXLSDataSource() */
41 : /************************************************************************/
42 :
43 5 : OGRXLSDataSource::OGRXLSDataSource()
44 5 : : pszName(nullptr), papoLayers(nullptr), nLayers(0), xlshandle(nullptr)
45 : {
46 5 : }
47 :
48 : /************************************************************************/
49 : /* ~OGRXLSDataSource() */
50 : /************************************************************************/
51 :
52 10 : OGRXLSDataSource::~OGRXLSDataSource()
53 :
54 : {
55 9 : for (int i = 0; i < nLayers; i++)
56 4 : delete papoLayers[i];
57 5 : CPLFree(papoLayers);
58 :
59 5 : CPLFree(pszName);
60 :
61 5 : if (xlshandle)
62 4 : freexl_close(xlshandle);
63 : #ifdef _WIN32
64 : if (m_osTempFilename.empty())
65 : {
66 : VSIUnlink(m_osTempFilename);
67 : }
68 : #endif
69 10 : }
70 :
71 : /************************************************************************/
72 : /* TestCapability() */
73 : /************************************************************************/
74 :
75 7 : int OGRXLSDataSource::TestCapability(CPL_UNUSED const char *pszCap)
76 :
77 : {
78 7 : return FALSE;
79 : }
80 :
81 : /************************************************************************/
82 : /* GetLayer() */
83 : /************************************************************************/
84 :
85 28 : OGRLayer *OGRXLSDataSource::GetLayer(int iLayer)
86 :
87 : {
88 28 : if (iLayer < 0 || iLayer >= nLayers)
89 2 : return nullptr;
90 : else
91 26 : return papoLayers[iLayer];
92 : }
93 :
94 : /************************************************************************/
95 : /* Open() */
96 : /************************************************************************/
97 :
98 5 : int OGRXLSDataSource::Open(const char *pszFilename, int bUpdateIn)
99 :
100 : {
101 5 : if (bUpdateIn)
102 : {
103 0 : return FALSE;
104 : }
105 :
106 5 : pszName = CPLStrdup(pszFilename);
107 5 : m_osANSIFilename = pszFilename;
108 : #ifdef _WIN32
109 : if (CPLTestBool(CPLGetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")))
110 : {
111 : CPLErrorReset();
112 : CPLPushErrorHandler(CPLQuietErrorHandler);
113 : char *pszTmpName = CPLRecode(pszFilename, CPL_ENC_UTF8,
114 : CPLString().Printf("CP%d", GetACP()));
115 : CPLPopErrorHandler();
116 : m_osANSIFilename = pszTmpName;
117 : CPLFree(pszTmpName);
118 :
119 : // In case recoding to the ANSI code page failed, then create a
120 : // temporary file in a "safe" location
121 : if (CPLGetLastErrorType() != CE_None)
122 : {
123 : CPLErrorReset();
124 :
125 : // FIXME: CPLGenerateTempFilename() would normally be expected to
126 : // return a UTF-8 filename but I doubt it does in all cases.
127 : m_osTempFilename = CPLGenerateTempFilename("temp_xls");
128 : m_osANSIFilename = m_osTempFilename;
129 : CPLCopyFile(m_osANSIFilename, pszFilename);
130 : CPLDebug("XLS", "Create temporary file: %s",
131 : m_osTempFilename.c_str());
132 : }
133 : }
134 : #endif
135 :
136 : // --------------------------------------------------------------------
137 : // Does this appear to be a .xls file?
138 : // --------------------------------------------------------------------
139 :
140 : /* Open only for getting info. To get cell values, we have to use
141 : * freexl_open */
142 5 : if (!GetXLSHandle())
143 1 : return FALSE;
144 :
145 4 : unsigned int nSheets = 0;
146 4 : if (freexl_get_info(xlshandle, FREEXL_BIFF_SHEET_COUNT, &nSheets) !=
147 : FREEXL_OK)
148 0 : return FALSE;
149 :
150 16 : for (unsigned short i = 0; i < (unsigned short)nSheets; i++)
151 : {
152 12 : freexl_select_active_worksheet(xlshandle, i);
153 :
154 12 : const char *pszSheetname = nullptr;
155 12 : if (freexl_get_worksheet_name(xlshandle, i, &pszSheetname) != FREEXL_OK)
156 0 : return FALSE;
157 :
158 12 : unsigned int nRows = 0;
159 12 : unsigned short nCols = 0;
160 12 : if (freexl_worksheet_dimensions(xlshandle, &nRows, &nCols) != FREEXL_OK)
161 0 : return FALSE;
162 :
163 : /* Skip empty sheets */
164 12 : if (nRows == 0)
165 8 : continue;
166 :
167 8 : papoLayers = (OGRLayer **)CPLRealloc(
168 4 : papoLayers, (nLayers + 1) * sizeof(OGRLayer *));
169 4 : papoLayers[nLayers++] =
170 4 : new OGRXLSLayer(this, pszSheetname, i, (int)nRows, nCols);
171 : }
172 :
173 4 : freexl_close(xlshandle);
174 4 : xlshandle = nullptr;
175 :
176 4 : return TRUE;
177 : }
178 :
179 : /************************************************************************/
180 : /* GetXLSHandle() */
181 : /************************************************************************/
182 :
183 69 : const void *OGRXLSDataSource::GetXLSHandle()
184 : {
185 69 : if (xlshandle)
186 61 : return xlshandle;
187 :
188 8 : if (freexl_open(m_osANSIFilename, &xlshandle) != FREEXL_OK)
189 1 : return nullptr;
190 :
191 7 : return xlshandle;
192 : }
|