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 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "include_freexl.h" 14 : 15 : #ifdef _WIN32 16 : #include <windows.h> 17 : #endif 18 : 19 : #include "ogr_xls.h" 20 : #include "cpl_conv.h" 21 : #include "cpl_string.h" 22 : 23 : /************************************************************************/ 24 : /* OGRXLSDataSource() */ 25 : /************************************************************************/ 26 : 27 5 : OGRXLSDataSource::OGRXLSDataSource() 28 5 : : papoLayers(nullptr), nLayers(0), xlshandle(nullptr) 29 : { 30 5 : } 31 : 32 : /************************************************************************/ 33 : /* ~OGRXLSDataSource() */ 34 : /************************************************************************/ 35 : 36 10 : OGRXLSDataSource::~OGRXLSDataSource() 37 : 38 : { 39 9 : for (int i = 0; i < nLayers; i++) 40 4 : delete papoLayers[i]; 41 5 : CPLFree(papoLayers); 42 : 43 5 : if (xlshandle) 44 4 : freexl_close(xlshandle); 45 : #ifdef _WIN32 46 : if (m_osTempFilename.empty()) 47 : { 48 : VSIUnlink(m_osTempFilename); 49 : } 50 : #endif 51 10 : } 52 : 53 : /************************************************************************/ 54 : /* GetLayer() */ 55 : /************************************************************************/ 56 : 57 28 : OGRLayer *OGRXLSDataSource::GetLayer(int iLayer) 58 : 59 : { 60 28 : if (iLayer < 0 || iLayer >= nLayers) 61 2 : return nullptr; 62 : else 63 26 : return papoLayers[iLayer]; 64 : } 65 : 66 : /************************************************************************/ 67 : /* Open() */ 68 : /************************************************************************/ 69 : 70 5 : int OGRXLSDataSource::Open(const char *pszFilename, int bUpdateIn) 71 : 72 : { 73 5 : if (bUpdateIn) 74 : { 75 0 : return FALSE; 76 : } 77 : 78 5 : m_osANSIFilename = pszFilename; 79 : #ifdef _WIN32 80 : if (CPLTestBool(CPLGetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"))) 81 : { 82 : CPLErrorReset(); 83 : CPLPushErrorHandler(CPLQuietErrorHandler); 84 : char *pszTmpName = CPLRecode(pszFilename, CPL_ENC_UTF8, 85 : CPLString().Printf("CP%d", GetACP())); 86 : CPLPopErrorHandler(); 87 : m_osANSIFilename = pszTmpName; 88 : CPLFree(pszTmpName); 89 : 90 : // In case recoding to the ANSI code page failed, then create a 91 : // temporary file in a "safe" location 92 : if (CPLGetLastErrorType() != CE_None) 93 : { 94 : CPLErrorReset(); 95 : 96 : // FIXME: CPLGenerateTempFilename() would normally be expected to 97 : // return a UTF-8 filename but I doubt it does in all cases. 98 : m_osTempFilename = CPLGenerateTempFilename("temp_xls"); 99 : m_osANSIFilename = m_osTempFilename; 100 : CPLCopyFile(m_osANSIFilename, pszFilename); 101 : CPLDebug("XLS", "Create temporary file: %s", 102 : m_osTempFilename.c_str()); 103 : } 104 : } 105 : #endif 106 : 107 : // -------------------------------------------------------------------- 108 : // Does this appear to be a .xls file? 109 : // -------------------------------------------------------------------- 110 : 111 : /* Open only for getting info. To get cell values, we have to use 112 : * freexl_open */ 113 5 : if (!GetXLSHandle()) 114 1 : return FALSE; 115 : 116 4 : unsigned int nSheets = 0; 117 4 : if (freexl_get_info(xlshandle, FREEXL_BIFF_SHEET_COUNT, &nSheets) != 118 : FREEXL_OK) 119 0 : return FALSE; 120 : 121 16 : for (unsigned short i = 0; i < (unsigned short)nSheets; i++) 122 : { 123 12 : freexl_select_active_worksheet(xlshandle, i); 124 : 125 12 : const char *pszSheetname = nullptr; 126 12 : if (freexl_get_worksheet_name(xlshandle, i, &pszSheetname) != FREEXL_OK) 127 0 : return FALSE; 128 : 129 12 : unsigned int nRows = 0; 130 12 : unsigned short nCols = 0; 131 12 : if (freexl_worksheet_dimensions(xlshandle, &nRows, &nCols) != FREEXL_OK) 132 0 : return FALSE; 133 : 134 : /* Skip empty sheets */ 135 12 : if (nRows == 0) 136 8 : continue; 137 : 138 8 : papoLayers = (OGRLayer **)CPLRealloc( 139 4 : papoLayers, (nLayers + 1) * sizeof(OGRLayer *)); 140 4 : papoLayers[nLayers++] = 141 4 : new OGRXLSLayer(this, pszSheetname, i, (int)nRows, nCols); 142 : } 143 : 144 4 : freexl_close(xlshandle); 145 4 : xlshandle = nullptr; 146 : 147 4 : return TRUE; 148 : } 149 : 150 : /************************************************************************/ 151 : /* GetXLSHandle() */ 152 : /************************************************************************/ 153 : 154 69 : const void *OGRXLSDataSource::GetXLSHandle() 155 : { 156 69 : if (xlshandle) 157 61 : return xlshandle; 158 : 159 8 : if (freexl_open(m_osANSIFilename, &xlshandle) != FREEXL_OK) 160 1 : return nullptr; 161 : 162 7 : return xlshandle; 163 : }