LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/xls - ogrxlslayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 141 130 92.2 %
Date: 2012-04-28 Functions: 13 10 76.9 %

       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               8 : OGRXLSLayer::OGRXLSLayer( OGRXLSDataSource* poDSIn,
      43                 :                           const char* pszSheetname,
      44                 :                           int iSheetIn,
      45                 :                           int nRowsIn,
      46               8 :                           unsigned short nColsIn )
      47                 : 
      48                 : {
      49               8 :     poDS = poDSIn;
      50               8 :     iSheet = iSheetIn;
      51               8 :     nNextFID = 0;
      52               8 :     bFirstLineIsHeaders = FALSE;
      53               8 :     poFeatureDefn = NULL;
      54               8 :     pszName = CPLStrdup(pszSheetname);
      55               8 :     nRows = nRowsIn;
      56               8 :     nCols = nColsIn;
      57               8 : }
      58                 : 
      59                 : /************************************************************************/
      60                 : /*                            ~OGRXLSLayer()                            */
      61                 : /************************************************************************/
      62                 : 
      63               8 : OGRXLSLayer::~OGRXLSLayer()
      64                 : 
      65                 : {
      66               8 :     CPLFree(pszName);
      67               8 :     if (poFeatureDefn)
      68               6 :         poFeatureDefn->Release();
      69               8 : }
      70                 : 
      71                 : /************************************************************************/
      72                 : /*                            ResetReading()                            */
      73                 : /************************************************************************/
      74                 : 
      75              36 : void OGRXLSLayer::ResetReading()
      76                 : 
      77                 : {
      78              36 :     if (poFeatureDefn != NULL)
      79                 :     {
      80              36 :         nNextFID = bFirstLineIsHeaders ? 1 : 0;
      81                 :     }
      82              36 : }
      83                 : 
      84                 : /************************************************************************/
      85                 : /*                          DetectHeaderLine()                          */
      86                 : /************************************************************************/
      87                 : 
      88               6 : void OGRXLSLayer::DetectHeaderLine(const void* xlshandle)
      89                 : 
      90                 : {
      91                 :     unsigned short i;
      92                 :     FreeXL_CellValue sCellValue;
      93               6 :     int nCountTextOnSecondLine = 0;
      94              36 :     for(i = 0; i < nCols && nRows >= 2; i ++)
      95                 :     {
      96              30 :         if (freexl_get_cell_value(xlshandle, 0, i, &sCellValue) == FREEXL_OK)
      97                 :         {
      98              30 :             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              30 :         if (freexl_get_cell_value(xlshandle, 1, i, &sCellValue) == FREEXL_OK)
     107                 :         {
     108              30 :             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               6 :     const char* pszXLSHeaders = CPLGetConfigOption("OGR_XLS_HEADERS", "");
     119               6 :     if (EQUAL(pszXLSHeaders, "FORCE"))
     120               0 :         bFirstLineIsHeaders = TRUE;
     121               6 :     else if (EQUAL(pszXLSHeaders, "DISABLE"))
     122               0 :         bFirstLineIsHeaders = FALSE;
     123               6 :     else if (i == nCols && nCountTextOnSecondLine != nCols)
     124               6 :         bFirstLineIsHeaders = TRUE;
     125               6 : }
     126                 : 
     127                 : /************************************************************************/
     128                 : /*                         DetectColumnTypes()                          */
     129                 : /************************************************************************/
     130                 : 
     131               4 : void OGRXLSLayer::DetectColumnTypes(const void* xlshandle,
     132                 :                                     int* paeFieldTypes)
     133                 : 
     134                 : {
     135                 :     int j;
     136                 :     unsigned short i;
     137                 :     FreeXL_CellValue sCellValue;
     138              16 :     for(j = bFirstLineIsHeaders ? 1 : 0; j < nRows; j ++)
     139                 :     {
     140              72 :         for(i = 0; i < nCols; i ++)
     141                 :         {
     142              60 :             if (freexl_get_cell_value(xlshandle, j, i, &sCellValue) == FREEXL_OK)
     143                 :             {
     144              60 :                 OGRFieldType eType = (OGRFieldType) paeFieldTypes[i];
     145              60 :                 switch (sCellValue.type)
     146                 :                 {
     147                 :                     case FREEXL_CELL_INT:
     148              16 :                         eType = OFTInteger;
     149              16 :                         break;
     150                 :                     case FREEXL_CELL_DOUBLE:
     151               4 :                         eType = OFTReal;
     152               4 :                         break;
     153                 :                     case FREEXL_CELL_TEXT:
     154                 :                     case FREEXL_CELL_SST_TEXT:
     155               8 :                         eType = OFTString;
     156               8 :                         break;
     157                 :                     case FREEXL_CELL_DATE:
     158              12 :                         eType = OFTDate;
     159              12 :                         break;
     160                 :                     case FREEXL_CELL_DATETIME:
     161               4 :                         eType = OFTDateTime;
     162               4 :                         break;
     163                 :                     case FREEXL_CELL_TIME:
     164               4 :                         eType = OFTTime;
     165                 :                         break;
     166                 :                     case FREEXL_CELL_NULL:
     167                 :                         break;
     168                 :                     default:
     169                 :                         break;
     170                 :                 }
     171                 : 
     172              60 :                 if (paeFieldTypes[i] < 0)
     173                 :                 {
     174              24 :                     paeFieldTypes[i] = (int) eType;
     175                 :                 }
     176              36 :                 else if ((int)eType != paeFieldTypes[i])
     177                 :                 {
     178              48 :                     if ((paeFieldTypes[i] == OFTDate ||
     179              12 :                          paeFieldTypes[i] == OFTTime ||
     180              12 :                          paeFieldTypes[i] == OFTDateTime) &&
     181                 :                         (eType == OFTDate || eType == OFTTime || eType == OFTDateTime))
     182               8 :                         paeFieldTypes[i] = OFTDateTime;
     183               8 :                     else if (paeFieldTypes[i] == OFTReal && eType == OFTInteger)
     184                 :                         /* nothing */ ;
     185               8 :                     else if (paeFieldTypes[i] == OFTInteger && eType == OFTReal)
     186               4 :                         paeFieldTypes[i] = OFTReal;
     187                 :                     else
     188               0 :                         paeFieldTypes[i] = OFTString;
     189                 :                 }
     190                 :             }
     191                 :         }
     192                 :     }
     193               4 : }
     194                 : 
     195                 : /************************************************************************/
     196                 : /*                            GetLayerDefn()                            */
     197                 : /************************************************************************/
     198                 : 
     199             126 : OGRFeatureDefn * OGRXLSLayer::GetLayerDefn()
     200                 : {
     201             126 :     if (poFeatureDefn)
     202             120 :         return poFeatureDefn;
     203                 : 
     204               6 :     poFeatureDefn = new OGRFeatureDefn( pszName );
     205               6 :     poFeatureDefn->Reference();
     206               6 :     poFeatureDefn->SetGeomType( wkbNone );
     207                 : 
     208               6 :     const void* xlshandle = poDS->GetXLSHandle();
     209               6 :     if (xlshandle == NULL)
     210               0 :         return poFeatureDefn;
     211                 : 
     212               6 :     freexl_select_active_worksheet(xlshandle, iSheet);
     213                 : 
     214               6 :     if (nRows > 0)
     215                 :     {
     216                 :         unsigned short i;
     217                 :         FreeXL_CellValue sCellValue;
     218                 : 
     219               6 :         DetectHeaderLine(xlshandle);
     220                 : 
     221                 :         int* paeFieldTypes = (int* )
     222               6 :                             CPLMalloc(nCols * sizeof(int));
     223              36 :         for(i = 0; i < nCols; i ++)
     224                 :         {
     225              30 :             paeFieldTypes[i] = -1;
     226                 :         }
     227                 : 
     228                 :         const char* pszXLSFieldTypes =
     229               6 :                         CPLGetConfigOption("OGR_XLS_FIELD_TYPES", "");
     230               6 :         if (!EQUAL(pszXLSFieldTypes, "STRING"))
     231               4 :             DetectColumnTypes(xlshandle, paeFieldTypes);
     232                 : 
     233              36 :         for(i = 0; i < nCols; i ++)
     234                 :         {
     235              30 :             OGRFieldType eType = (OGRFieldType) paeFieldTypes[i];
     236              30 :             if (paeFieldTypes[i] < 0)
     237              10 :                 eType = OFTString;
     238              30 :             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              30 :                 OGRFieldDefn oField(sCellValue.value.text_value, eType);
     244              30 :                 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               6 :         CPLFree(paeFieldTypes);
     254                 : 
     255                 :     }
     256                 : 
     257               6 :     ResetReading();
     258                 : 
     259               6 :     return poFeatureDefn;
     260                 : }
     261                 : 
     262                 : /************************************************************************/
     263                 : /*                          GetFeatureCount()                           */
     264                 : /************************************************************************/
     265                 : 
     266              16 : int OGRXLSLayer::GetFeatureCount( int bForce )
     267                 : {
     268              16 :     if  ( m_poAttrQuery == NULL /* && m_poFilterGeom == NULL */ )
     269                 :     {
     270              12 :         const char* pszXLSHeaders = CPLGetConfigOption("OGR_XLS_HEADERS", "");
     271              12 :         if(EQUAL(pszXLSHeaders, "DISABLE"))
     272               2 :             return nRows;
     273                 : 
     274              10 :         GetLayerDefn();
     275              10 :         return bFirstLineIsHeaders ? nRows - 1 : nRows;
     276                 :     }
     277                 : 
     278               4 :     return OGRLayer::GetFeatureCount(bForce);
     279                 : }
     280                 : 
     281                 : /************************************************************************/
     282                 : /*                           GetNextFeature()                           */
     283                 : /************************************************************************/
     284                 : 
     285              46 : OGRFeature *OGRXLSLayer::GetNextFeature()
     286                 : {
     287              46 :     GetLayerDefn();
     288                 : 
     289                 :     OGRFeature  *poFeature;
     290                 : 
     291               8 :     while(TRUE)
     292                 :     {
     293              54 :         poFeature = GetNextRawFeature();
     294              54 :         if (poFeature == NULL)
     295              12 :             return NULL;
     296                 : 
     297              42 :         if(/*(m_poFilterGeom == NULL
     298                 :             || FilterGeometry( poFeature->GetGeometryRef() ) )
     299                 :         && */ (m_poAttrQuery == NULL
     300                 :             || m_poAttrQuery->Evaluate( poFeature )) )
     301                 :         {
     302              34 :             return poFeature;
     303                 :         }
     304                 :         else
     305               8 :             delete poFeature;
     306                 :     }
     307                 : }
     308                 : 
     309                 : /************************************************************************/
     310                 : /*                         GetNextRawFeature()                          */
     311                 : /************************************************************************/
     312                 : 
     313              54 : OGRFeature *OGRXLSLayer::GetNextRawFeature()
     314                 : {
     315              54 :     if (nNextFID == nRows)
     316              12 :         return NULL;
     317                 : 
     318              42 :     const void* xlshandle = poDS->GetXLSHandle();
     319              42 :     if (xlshandle == NULL)
     320               0 :         return NULL;
     321                 : 
     322              42 :     freexl_select_active_worksheet(xlshandle, iSheet);
     323                 : 
     324              42 :     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
     325                 : 
     326                 :     FreeXL_CellValue sCellValue;
     327             252 :     for(unsigned short i=0;i<(unsigned short )poFeatureDefn->GetFieldCount(); i++)
     328                 :     {
     329             210 :         if (freexl_get_cell_value(xlshandle, nNextFID, i, &sCellValue) == FREEXL_OK)
     330                 :         {
     331             210 :             switch (sCellValue.type)
     332                 :             {
     333                 :                 case FREEXL_CELL_INT:
     334              60 :                     poFeature->SetField(i, sCellValue.value.int_value);
     335              60 :                     break;
     336                 :                 case FREEXL_CELL_DOUBLE:
     337              12 :                     poFeature->SetField(i, sCellValue.value.double_value);
     338              12 :                     break;
     339                 :                 case FREEXL_CELL_TEXT:
     340                 :                 case FREEXL_CELL_SST_TEXT:
     341              24 :                     poFeature->SetField(i, sCellValue.value.text_value);
     342              24 :                     break;
     343                 :                 case FREEXL_CELL_DATE:
     344                 :                 case FREEXL_CELL_DATETIME:
     345                 :                 case FREEXL_CELL_TIME:
     346              72 :                     poFeature->SetField(i, sCellValue.value.text_value);
     347              72 :                     break;
     348                 :                 case FREEXL_CELL_NULL:
     349              42 :                     break;
     350                 :                 default:
     351               0 :                     CPLDebug("XLS", "Unknown cell type = %d", sCellValue.type);
     352                 :                     break;
     353                 :             }
     354                 :         }
     355                 :     }
     356                 : 
     357              42 :     poFeature->SetFID(nNextFID + 1);
     358              42 :     nNextFID ++;
     359                 : 
     360              42 :     return poFeature;
     361                 : }
     362                 : 
     363                 : /************************************************************************/
     364                 : /*                           TestCapability()                           */
     365                 : /************************************************************************/
     366                 : 
     367              14 : int OGRXLSLayer::TestCapability( const char * pszCap )
     368                 : 
     369                 : {
     370              14 :     if( EQUAL(pszCap, OLCFastFeatureCount) )
     371               0 :         return m_poAttrQuery == NULL /* && m_poFilterGeom == NULL */;
     372                 : 
     373              14 :     return FALSE;
     374                 : }
     375                 : 

Generated by: LCOV version 1.7