1 /******************************************************************************
2  * $Id: ogrxlsdatasource.cpp 28382 2015-01-30 15:29:41Z rouault $
3  *
4  * Project:  XLS Translator
5  * Purpose:  Implements OGRXLSDataSource 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-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 #ifdef _WIN32
33 #  include <windows.h>
34 #endif
35 
36 #include "ogr_xls.h"
37 #include "cpl_conv.h"
38 #include "cpl_string.h"
39 
40 CPL_CVSID("$Id: ogrxlsdatasource.cpp 28382 2015-01-30 15:29:41Z rouault $");
41 
42 /************************************************************************/
43 /*                          OGRXLSDataSource()                          */
44 /************************************************************************/
45 
OGRXLSDataSource()46 OGRXLSDataSource::OGRXLSDataSource()
47 
48 {
49     papoLayers = NULL;
50     nLayers = 0;
51 
52     pszName = NULL;
53 
54     xlshandle = NULL;
55 }
56 
57 /************************************************************************/
58 /*                         ~OGRXLSDataSource()                          */
59 /************************************************************************/
60 
~OGRXLSDataSource()61 OGRXLSDataSource::~OGRXLSDataSource()
62 
63 {
64     for( int i = 0; i < nLayers; i++ )
65         delete papoLayers[i];
66     CPLFree( papoLayers );
67 
68     CPLFree( pszName );
69 
70     if (xlshandle)
71         freexl_close(xlshandle);
72 }
73 
74 /************************************************************************/
75 /*                           TestCapability()                           */
76 /************************************************************************/
77 
TestCapability(CPL_UNUSED const char * pszCap)78 int OGRXLSDataSource::TestCapability( CPL_UNUSED const char * pszCap )
79 
80 {
81     return FALSE;
82 }
83 
84 /************************************************************************/
85 /*                              GetLayer()                              */
86 /************************************************************************/
87 
GetLayer(int iLayer)88 OGRLayer *OGRXLSDataSource::GetLayer( int iLayer )
89 
90 {
91     if( iLayer < 0 || iLayer >= nLayers )
92         return NULL;
93     else
94         return papoLayers[iLayer];
95 }
96 
97 /************************************************************************/
98 /*                                Open()                                */
99 /************************************************************************/
100 
Open(const char * pszFilename,int bUpdateIn)101 int OGRXLSDataSource::Open( const char * pszFilename, int bUpdateIn)
102 
103 {
104     if (bUpdateIn)
105     {
106         return FALSE;
107     }
108 
109 #ifdef _WIN32
110     if( CSLTestBoolean( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
111         pszName = CPLRecode( pszFilename, CPL_ENC_UTF8, CPLString().Printf( "CP%d", GetACP() ) );
112     else
113         pszName = CPLStrdup( pszFilename );
114 #else
115     pszName = CPLStrdup( pszFilename );
116 #endif
117 
118 // --------------------------------------------------------------------
119 //      Does this appear to be a .xls file?
120 // --------------------------------------------------------------------
121 
122     /* Open only for getting info. To get cell values, we have to use freexl_open */
123     if (freexl_open_info (pszName, &xlshandle) != FREEXL_OK)
124         return FALSE;
125 
126     unsigned int nSheets = 0;
127     if (freexl_get_info (xlshandle, FREEXL_BIFF_SHEET_COUNT, &nSheets) != FREEXL_OK)
128         return FALSE;
129 
130     for(unsigned short i=0; i<(unsigned short)nSheets; i++)
131     {
132         freexl_select_active_worksheet(xlshandle, i);
133 
134         const char* pszSheetname = NULL;
135         if (freexl_get_worksheet_name(xlshandle, i, &pszSheetname) != FREEXL_OK)
136             return FALSE;
137 
138         unsigned int nRows = 0;
139         unsigned short nCols = 0;
140         if (freexl_worksheet_dimensions(xlshandle, &nRows, &nCols) != FREEXL_OK)
141             return FALSE;
142 
143         /* Skip empty sheets */
144         if (nRows == 0)
145             continue;
146 
147         papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
148         papoLayers[nLayers ++] = new OGRXLSLayer(this, pszSheetname, i, (int)nRows, nCols);
149     }
150 
151     freexl_close(xlshandle);
152     xlshandle = NULL;
153 
154     return TRUE;
155 }
156 
157 /************************************************************************/
158 /*                           GetXLSHandle()                             */
159 /************************************************************************/
160 
GetXLSHandle()161 const void* OGRXLSDataSource::GetXLSHandle()
162 {
163     if (xlshandle)
164         return xlshandle;
165 
166     if (freexl_open (pszName, &xlshandle) != FREEXL_OK)
167         return NULL;
168 
169     return xlshandle;
170 }
171