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-12-26 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               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                 : 

Generated by: LCOV version 1.7