1 : /******************************************************************************
2 : * $Id: ogrxlslayer.cpp 24172 2012-03-29 19:16:09Z rouault $
3 : *
4 : * Project: XLS Translator
5 : * Purpose: Implements OGRXLSLayer class.
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include <freexl.h>
31 :
32 : #include "ogr_xls.h"
33 : #include "cpl_conv.h"
34 : #include "cpl_string.h"
35 :
36 : CPL_CVSID("$Id: ogrxlslayer.cpp 24172 2012-03-29 19:16:09Z rouault $");
37 :
38 : /************************************************************************/
39 : /* OGRXLSLayer() */
40 : /************************************************************************/
41 :
42 4 : OGRXLSLayer::OGRXLSLayer( OGRXLSDataSource* poDSIn,
43 : const char* pszSheetname,
44 : int iSheetIn,
45 : int nRowsIn,
46 4 : unsigned short nColsIn )
47 :
48 : {
49 4 : poDS = poDSIn;
50 4 : iSheet = iSheetIn;
51 4 : nNextFID = 0;
52 4 : bFirstLineIsHeaders = FALSE;
53 4 : poFeatureDefn = NULL;
54 4 : pszName = CPLStrdup(pszSheetname);
55 4 : nRows = nRowsIn;
56 4 : nCols = nColsIn;
57 4 : }
58 :
59 : /************************************************************************/
60 : /* ~OGRXLSLayer() */
61 : /************************************************************************/
62 :
63 4 : OGRXLSLayer::~OGRXLSLayer()
64 :
65 : {
66 4 : CPLFree(pszName);
67 4 : if (poFeatureDefn)
68 3 : poFeatureDefn->Release();
69 4 : }
70 :
71 : /************************************************************************/
72 : /* ResetReading() */
73 : /************************************************************************/
74 :
75 24 : void OGRXLSLayer::ResetReading()
76 :
77 : {
78 24 : if (poFeatureDefn != NULL)
79 : {
80 24 : nNextFID = bFirstLineIsHeaders ? 1 : 0;
81 : }
82 24 : }
83 :
84 : /************************************************************************/
85 : /* DetectHeaderLine() */
86 : /************************************************************************/
87 :
88 3 : void OGRXLSLayer::DetectHeaderLine(const void* xlshandle)
89 :
90 : {
91 : unsigned short i;
92 : FreeXL_CellValue sCellValue;
93 3 : int nCountTextOnSecondLine = 0;
94 18 : for(i = 0; i < nCols && nRows >= 2; i ++)
95 : {
96 15 : if (freexl_get_cell_value(xlshandle, 0, i, &sCellValue) == FREEXL_OK)
97 : {
98 15 : if (sCellValue.type != FREEXL_CELL_TEXT &&
99 : sCellValue.type != FREEXL_CELL_SST_TEXT)
100 : {
101 : /* If the values in the first line are not text, then it is */
102 : /* not a header line */
103 0 : break;
104 : }
105 : }
106 15 : if (freexl_get_cell_value(xlshandle, 1, i, &sCellValue) == FREEXL_OK)
107 : {
108 15 : if (sCellValue.type == FREEXL_CELL_TEXT ||
109 : sCellValue.type == FREEXL_CELL_SST_TEXT)
110 : {
111 : /* If there are only text values on the second line, then we cannot */
112 : /* know if it is a header line or just a regular line */
113 0 : nCountTextOnSecondLine ++;
114 : }
115 : }
116 : }
117 :
118 3 : const char* pszXLSHeaders = CPLGetConfigOption("OGR_XLS_HEADERS", "");
119 3 : if (EQUAL(pszXLSHeaders, "FORCE"))
120 0 : bFirstLineIsHeaders = TRUE;
121 3 : else if (EQUAL(pszXLSHeaders, "DISABLE"))
122 0 : bFirstLineIsHeaders = FALSE;
123 3 : else if (i == nCols && nCountTextOnSecondLine != nCols)
124 3 : bFirstLineIsHeaders = TRUE;
125 3 : }
126 :
127 : /************************************************************************/
128 : /* DetectColumnTypes() */
129 : /************************************************************************/
130 :
131 2 : void OGRXLSLayer::DetectColumnTypes(const void* xlshandle,
132 : int* paeFieldTypes)
133 :
134 : {
135 : int j;
136 : unsigned short i;
137 : FreeXL_CellValue sCellValue;
138 8 : for(j = bFirstLineIsHeaders ? 1 : 0; j < nRows; j ++)
139 : {
140 36 : for(i = 0; i < nCols; i ++)
141 : {
142 30 : if (freexl_get_cell_value(xlshandle, j, i, &sCellValue) == FREEXL_OK)
143 : {
144 30 : OGRFieldType eType = (OGRFieldType) paeFieldTypes[i];
145 30 : switch (sCellValue.type)
146 : {
147 : case FREEXL_CELL_INT:
148 8 : eType = OFTInteger;
149 8 : break;
150 : case FREEXL_CELL_DOUBLE:
151 2 : eType = OFTReal;
152 2 : break;
153 : case FREEXL_CELL_TEXT:
154 : case FREEXL_CELL_SST_TEXT:
155 4 : eType = OFTString;
156 4 : break;
157 : case FREEXL_CELL_DATE:
158 6 : eType = OFTDate;
159 6 : break;
160 : case FREEXL_CELL_DATETIME:
161 2 : eType = OFTDateTime;
162 2 : break;
163 : case FREEXL_CELL_TIME:
164 2 : eType = OFTTime;
165 : break;
166 : case FREEXL_CELL_NULL:
167 : break;
168 : default:
169 : break;
170 : }
171 :
172 30 : if (paeFieldTypes[i] < 0)
173 : {
174 12 : paeFieldTypes[i] = (int) eType;
175 : }
176 18 : else if ((int)eType != paeFieldTypes[i])
177 : {
178 24 : if ((paeFieldTypes[i] == OFTDate ||
179 6 : paeFieldTypes[i] == OFTTime ||
180 6 : paeFieldTypes[i] == OFTDateTime) &&
181 : (eType == OFTDate || eType == OFTTime || eType == OFTDateTime))
182 4 : paeFieldTypes[i] = OFTDateTime;
183 4 : else if (paeFieldTypes[i] == OFTReal && eType == OFTInteger)
184 : /* nothing */ ;
185 4 : else if (paeFieldTypes[i] == OFTInteger && eType == OFTReal)
186 2 : paeFieldTypes[i] = OFTReal;
187 : else
188 0 : paeFieldTypes[i] = OFTString;
189 : }
190 : }
191 : }
192 : }
193 2 : }
194 :
195 : /************************************************************************/
196 : /* GetLayerDefn() */
197 : /************************************************************************/
198 :
199 110 : OGRFeatureDefn * OGRXLSLayer::GetLayerDefn()
200 : {
201 110 : if (poFeatureDefn)
202 107 : return poFeatureDefn;
203 :
204 3 : poFeatureDefn = new OGRFeatureDefn( pszName );
205 3 : poFeatureDefn->Reference();
206 3 : poFeatureDefn->SetGeomType( wkbNone );
207 :
208 3 : const void* xlshandle = poDS->GetXLSHandle();
209 3 : if (xlshandle == NULL)
210 0 : return poFeatureDefn;
211 :
212 3 : freexl_select_active_worksheet(xlshandle, iSheet);
213 :
214 3 : if (nRows > 0)
215 : {
216 : unsigned short i;
217 : FreeXL_CellValue sCellValue;
218 :
219 3 : DetectHeaderLine(xlshandle);
220 :
221 : int* paeFieldTypes = (int* )
222 3 : CPLMalloc(nCols * sizeof(int));
223 18 : for(i = 0; i < nCols; i ++)
224 : {
225 15 : paeFieldTypes[i] = -1;
226 : }
227 :
228 : const char* pszXLSFieldTypes =
229 3 : CPLGetConfigOption("OGR_XLS_FIELD_TYPES", "");
230 3 : if (!EQUAL(pszXLSFieldTypes, "STRING"))
231 2 : DetectColumnTypes(xlshandle, paeFieldTypes);
232 :
233 18 : for(i = 0; i < nCols; i ++)
234 : {
235 15 : OGRFieldType eType = (OGRFieldType) paeFieldTypes[i];
236 15 : if (paeFieldTypes[i] < 0)
237 5 : eType = OFTString;
238 15 : if (bFirstLineIsHeaders &&
239 : freexl_get_cell_value(xlshandle, 0, i, &sCellValue) == FREEXL_OK &&
240 : (sCellValue.type == FREEXL_CELL_TEXT ||
241 : sCellValue.type == FREEXL_CELL_SST_TEXT))
242 : {
243 15 : OGRFieldDefn oField(sCellValue.value.text_value, eType);
244 15 : poFeatureDefn->AddFieldDefn(&oField);
245 : }
246 : else
247 : {
248 0 : OGRFieldDefn oField(CPLSPrintf("Field%d", i+1), eType);
249 0 : poFeatureDefn->AddFieldDefn(&oField);
250 : }
251 : }
252 :
253 3 : CPLFree(paeFieldTypes);
254 :
255 : }
256 :
257 3 : ResetReading();
258 :
259 3 : return poFeatureDefn;
260 : }
261 :
262 : /************************************************************************/
263 : /* GetFeatureCount() */
264 : /************************************************************************/
265 :
266 8 : int OGRXLSLayer::GetFeatureCount( int bForce )
267 : {
268 8 : if ( m_poAttrQuery == NULL /* && m_poFilterGeom == NULL */ )
269 : {
270 6 : const char* pszXLSHeaders = CPLGetConfigOption("OGR_XLS_HEADERS", "");
271 6 : if(EQUAL(pszXLSHeaders, "DISABLE"))
272 1 : return nRows;
273 :
274 5 : GetLayerDefn();
275 5 : return bFirstLineIsHeaders ? nRows - 1 : nRows;
276 : }
277 :
278 2 : return OGRLayer::GetFeatureCount(bForce);
279 : }
280 :
281 : /************************************************************************/
282 : /* GetNextFeature() */
283 : /************************************************************************/
284 :
285 34 : OGRFeature *OGRXLSLayer::GetNextFeature()
286 : {
287 34 : GetLayerDefn();
288 :
289 : OGRFeature *poFeature;
290 :
291 9 : while(TRUE)
292 : {
293 43 : poFeature = GetNextRawFeature();
294 43 : if (poFeature == NULL)
295 10 : return NULL;
296 :
297 33 : if(/*(m_poFilterGeom == NULL
298 : || FilterGeometry( poFeature->GetGeometryRef() ) )
299 : && */ (m_poAttrQuery == NULL
300 : || m_poAttrQuery->Evaluate( poFeature )) )
301 : {
302 24 : return poFeature;
303 : }
304 : else
305 9 : delete poFeature;
306 : }
307 : }
308 :
309 : /************************************************************************/
310 : /* GetNextRawFeature() */
311 : /************************************************************************/
312 :
313 43 : OGRFeature *OGRXLSLayer::GetNextRawFeature()
314 : {
315 43 : if (nNextFID == nRows)
316 10 : return NULL;
317 :
318 33 : const void* xlshandle = poDS->GetXLSHandle();
319 33 : if (xlshandle == NULL)
320 0 : return NULL;
321 :
322 33 : freexl_select_active_worksheet(xlshandle, iSheet);
323 :
324 33 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
325 :
326 : FreeXL_CellValue sCellValue;
327 198 : for(unsigned short i=0;i<(unsigned short )poFeatureDefn->GetFieldCount(); i++)
328 : {
329 165 : if (freexl_get_cell_value(xlshandle, nNextFID, i, &sCellValue) == FREEXL_OK)
330 : {
331 165 : switch (sCellValue.type)
332 : {
333 : case FREEXL_CELL_INT:
334 46 : poFeature->SetField(i, sCellValue.value.int_value);
335 46 : break;
336 : case FREEXL_CELL_DOUBLE:
337 10 : poFeature->SetField(i, sCellValue.value.double_value);
338 10 : break;
339 : case FREEXL_CELL_TEXT:
340 : case FREEXL_CELL_SST_TEXT:
341 20 : poFeature->SetField(i, sCellValue.value.text_value);
342 20 : break;
343 : case FREEXL_CELL_DATE:
344 : case FREEXL_CELL_DATETIME:
345 : case FREEXL_CELL_TIME:
346 56 : poFeature->SetField(i, sCellValue.value.text_value);
347 56 : break;
348 : case FREEXL_CELL_NULL:
349 33 : break;
350 : default:
351 0 : CPLDebug("XLS", "Unknown cell type = %d", sCellValue.type);
352 : break;
353 : }
354 : }
355 : }
356 :
357 33 : poFeature->SetFID(nNextFID + 1);
358 33 : nNextFID ++;
359 :
360 33 : return poFeature;
361 : }
362 :
363 : /************************************************************************/
364 : /* TestCapability() */
365 : /************************************************************************/
366 :
367 9 : int OGRXLSLayer::TestCapability( const char * pszCap )
368 :
369 : {
370 9 : if( EQUAL(pszCap, OLCFastFeatureCount) )
371 0 : return m_poAttrQuery == NULL /* && m_poFilterGeom == NULL */;
372 :
373 9 : return FALSE;
374 : }
375 :
|