EVOLUTION-MANAGER
Edit File: ogrxlslayer.cpp
/****************************************************************************** * * Project: XLS Translator * Purpose: Implements OGRXLSLayer class. * Author: Even Rouault, <even dot rouault at mines dash paris dot org> * ****************************************************************************** * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include <freexl.h> #include "ogr_xls.h" #include "cpl_conv.h" #include "cpl_string.h" CPL_CVSID("$Id: ogrxlslayer.cpp 35580 2016-10-01 17:02:59Z goatbar $"); /************************************************************************/ /* OGRXLSLayer() */ /************************************************************************/ OGRXLSLayer::OGRXLSLayer( OGRXLSDataSource* poDSIn, const char* pszSheetname, int iSheetIn, int nRowsIn, unsigned short nColsIn ) : poDS(poDSIn), poFeatureDefn(NULL), pszName(CPLStrdup(pszSheetname)), iSheet(iSheetIn), bFirstLineIsHeaders(false), nRows(nRowsIn), nCols(nColsIn), nNextFID(0) { SetDescription( pszName ); } /************************************************************************/ /* ~OGRXLSLayer() */ /************************************************************************/ OGRXLSLayer::~OGRXLSLayer() { CPLFree(pszName); if( poFeatureDefn ) poFeatureDefn->Release(); } /************************************************************************/ /* ResetReading() */ /************************************************************************/ void OGRXLSLayer::ResetReading() { if (poFeatureDefn != NULL) { nNextFID = bFirstLineIsHeaders ? 1 : 0; } } /************************************************************************/ /* DetectHeaderLine() */ /************************************************************************/ void OGRXLSLayer::DetectHeaderLine(const void* xlshandle) { FreeXL_CellValue sCellValue; int nCountTextOnSecondLine = 0; unsigned short i = 0; // Used after for. for( ; i < nCols && nRows >= 2; i++ ) { if (freexl_get_cell_value(xlshandle, 0, i, &sCellValue) == FREEXL_OK) { if (sCellValue.type != FREEXL_CELL_TEXT && sCellValue.type != FREEXL_CELL_SST_TEXT) { /* If the values in the first line are not text, then it is */ /* not a header line */ break; } } if (freexl_get_cell_value(xlshandle, 1, i, &sCellValue) == FREEXL_OK) { if (sCellValue.type == FREEXL_CELL_TEXT || sCellValue.type == FREEXL_CELL_SST_TEXT) { /* If there are only text values on the second line, then we cannot */ /* know if it is a header line or just a regular line */ nCountTextOnSecondLine ++; } } } const char* pszXLSHeaders = CPLGetConfigOption("OGR_XLS_HEADERS", ""); if( EQUAL(pszXLSHeaders, "FORCE") ) bFirstLineIsHeaders = true; else if( EQUAL(pszXLSHeaders, "DISABLE") ) bFirstLineIsHeaders = false; else if( i == nCols && nCountTextOnSecondLine != nCols ) bFirstLineIsHeaders = true; } /************************************************************************/ /* DetectColumnTypes() */ /************************************************************************/ void OGRXLSLayer::DetectColumnTypes(const void* xlshandle, int* paeFieldTypes) { FreeXL_CellValue sCellValue; for( int j = bFirstLineIsHeaders ? 1 : 0; j < nRows; j++ ) { for( unsigned short i = 0; i < nCols; i ++) { if (freexl_get_cell_value(xlshandle, j, i, &sCellValue) == FREEXL_OK) { OGRFieldType eType = (OGRFieldType) paeFieldTypes[i]; switch (sCellValue.type) { case FREEXL_CELL_INT: eType = OFTInteger; break; case FREEXL_CELL_DOUBLE: eType = OFTReal; break; case FREEXL_CELL_TEXT: case FREEXL_CELL_SST_TEXT: eType = OFTString; break; case FREEXL_CELL_DATE: eType = OFTDate; break; case FREEXL_CELL_DATETIME: eType = OFTDateTime; break; case FREEXL_CELL_TIME: eType = OFTTime; break; case FREEXL_CELL_NULL: break; default: break; } if (paeFieldTypes[i] < 0) { paeFieldTypes[i] = (int) eType; } else if ((int)eType != paeFieldTypes[i]) { if ((paeFieldTypes[i] == OFTDate || paeFieldTypes[i] == OFTTime || paeFieldTypes[i] == OFTDateTime) && (eType == OFTDate || eType == OFTTime || eType == OFTDateTime)) paeFieldTypes[i] = OFTDateTime; else if (paeFieldTypes[i] == OFTReal && eType == OFTInteger) /* nothing */ ; else if (paeFieldTypes[i] == OFTInteger && eType == OFTReal) paeFieldTypes[i] = OFTReal; else paeFieldTypes[i] = OFTString; } } } } } /************************************************************************/ /* GetLayerDefn() */ /************************************************************************/ OGRFeatureDefn * OGRXLSLayer::GetLayerDefn() { if (poFeatureDefn) return poFeatureDefn; poFeatureDefn = new OGRFeatureDefn( pszName ); poFeatureDefn->Reference(); poFeatureDefn->SetGeomType( wkbNone ); const void* xlshandle = poDS->GetXLSHandle(); if (xlshandle == NULL) return poFeatureDefn; freexl_select_active_worksheet(xlshandle, (unsigned short)iSheet); if (nRows > 0) { FreeXL_CellValue sCellValue; DetectHeaderLine(xlshandle); int* paeFieldTypes = (int* ) CPLMalloc(nCols * sizeof(int)); for( unsigned short i = 0; i < nCols; i++ ) { paeFieldTypes[i] = -1; } const char* pszXLSFieldTypes = CPLGetConfigOption("OGR_XLS_FIELD_TYPES", ""); if (!EQUAL(pszXLSFieldTypes, "STRING")) DetectColumnTypes(xlshandle, paeFieldTypes); for( unsigned short i = 0; i < nCols; i++ ) { OGRFieldType eType = (OGRFieldType) paeFieldTypes[i]; if (paeFieldTypes[i] < 0) eType = OFTString; if( bFirstLineIsHeaders && freexl_get_cell_value(xlshandle, 0, i, &sCellValue) == FREEXL_OK && (sCellValue.type == FREEXL_CELL_TEXT || sCellValue.type == FREEXL_CELL_SST_TEXT) ) { OGRFieldDefn oField(sCellValue.value.text_value, eType); poFeatureDefn->AddFieldDefn(&oField); } else { OGRFieldDefn oField(CPLSPrintf("Field%d", i+1), eType); poFeatureDefn->AddFieldDefn(&oField); } } CPLFree(paeFieldTypes); } ResetReading(); return poFeatureDefn; } /************************************************************************/ /* GetFeatureCount() */ /************************************************************************/ GIntBig OGRXLSLayer::GetFeatureCount( int bForce ) { if( m_poAttrQuery == NULL /* && m_poFilterGeom == NULL */ ) { const char* pszXLSHeaders = CPLGetConfigOption("OGR_XLS_HEADERS", ""); if(EQUAL(pszXLSHeaders, "DISABLE")) return nRows; GetLayerDefn(); return bFirstLineIsHeaders ? nRows - 1 : nRows; } return OGRLayer::GetFeatureCount(bForce); } /************************************************************************/ /* GetNextFeature() */ /************************************************************************/ OGRFeature *OGRXLSLayer::GetNextFeature() { GetLayerDefn(); while( true ) { OGRFeature *poFeature = GetNextRawFeature(); if (poFeature == NULL) return NULL; if(/*(m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) && */ (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) ) { return poFeature; } else delete poFeature; } } /************************************************************************/ /* GetNextRawFeature() */ /************************************************************************/ OGRFeature *OGRXLSLayer::GetNextRawFeature() { if (nNextFID == nRows) return NULL; const void* xlshandle = poDS->GetXLSHandle(); if (xlshandle == NULL) return NULL; freexl_select_active_worksheet(xlshandle, (unsigned short)iSheet); OGRFeature* poFeature = new OGRFeature(poFeatureDefn); FreeXL_CellValue sCellValue; for(unsigned short i=0;i<(unsigned short )poFeatureDefn->GetFieldCount(); i++) { if (freexl_get_cell_value(xlshandle, nNextFID, i, &sCellValue) == FREEXL_OK) { switch (sCellValue.type) { case FREEXL_CELL_INT: poFeature->SetField(i, sCellValue.value.int_value); break; case FREEXL_CELL_DOUBLE: poFeature->SetField(i, sCellValue.value.double_value); break; case FREEXL_CELL_TEXT: case FREEXL_CELL_SST_TEXT: poFeature->SetField(i, sCellValue.value.text_value); break; case FREEXL_CELL_DATE: case FREEXL_CELL_DATETIME: case FREEXL_CELL_TIME: poFeature->SetField(i, sCellValue.value.text_value); break; case FREEXL_CELL_NULL: break; default: CPLDebug("XLS", "Unknown cell type = %d", sCellValue.type); break; } } } poFeature->SetFID(nNextFID + 1); nNextFID ++; return poFeature; } /************************************************************************/ /* TestCapability() */ /************************************************************************/ int OGRXLSLayer::TestCapability( const char * pszCap ) { if( EQUAL(pszCap, OLCFastFeatureCount) ) return m_poAttrQuery == NULL /* && m_poFilterGeom == NULL */; return FALSE; }