LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/xlsx - ogr_xlsx.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 40 48 83.3 %
Date: 2026-01-23 20:24:11 Functions: 15 17 88.2 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  XLSX Translator
       4             :  * Purpose:  Definition of classes for OGR OpenOfficeSpreadsheet .xlsx driver.
       5             :  * Author:   Even Rouault, even dot rouault at spatialys.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2012, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef OGR_XLSX_H_INCLUDED
      14             : #define OGR_XLSX_H_INCLUDED
      15             : 
      16             : #include "ogrsf_frmts.h"
      17             : 
      18             : #include "ogr_expat.h"
      19             : #include "memdataset.h"
      20             : 
      21             : #include <vector>
      22             : #include <set>
      23             : #include <string>
      24             : #include <map>
      25             : 
      26             : namespace OGRXLSX
      27             : {
      28             : 
      29             : /************************************************************************/
      30             : /*                             OGRXLSXLayer                             */
      31             : /************************************************************************/
      32             : 
      33             : class OGRXLSXDataSource;
      34             : 
      35             : class OGRXLSXLayer final : public OGRMemLayer
      36             : {
      37             :     friend class OGRXLSXDataSource;
      38             : 
      39             :     bool bInit;
      40             :     OGRXLSXDataSource *poDS;
      41             :     CPLString osFilename;
      42             :     void Init();
      43             :     bool bUpdated;
      44             :     bool bHasHeaderLine;
      45             :     std::string m_osCols{};
      46             :     std::set<int> oSetFieldsOfUnknownType{};
      47             : 
      48             :     GIntBig TranslateFIDFromMemLayer(GIntBig nFID) const;
      49             :     GIntBig TranslateFIDToMemLayer(GIntBig nFID) const;
      50             : 
      51             :   public:
      52             :     OGRXLSXLayer(OGRXLSXDataSource *poDSIn, const char *pszFilename,
      53             :                  const char *pszName, int bUpdateIn = FALSE);
      54             : 
      55             :     bool HasBeenUpdated() const
      56             :     {
      57             :         return bUpdated;
      58             :     }
      59             : 
      60             :     void SetUpdated(bool bUpdatedIn = true);
      61             : 
      62             :     bool GetHasHeaderLine() const
      63             :     {
      64             :         return bHasHeaderLine;
      65             :     }
      66             : 
      67          60 :     void SetHasHeaderLine(bool bIn)
      68             :     {
      69          60 :         bHasHeaderLine = bIn;
      70          60 :     }
      71             : 
      72        1160 :     const char *GetName() const override
      73             :     {
      74        1160 :         return OGRMemLayer::GetLayerDefn()->GetName();
      75             :     }
      76             : 
      77          29 :     OGRwkbGeometryType GetGeomType() const override
      78             :     {
      79          29 :         return wkbNone;
      80             :     }
      81             : 
      82          10 :     const OGRSpatialReference *GetSpatialRef() const override
      83             :     {
      84          10 :         return nullptr;
      85             :     }
      86             : 
      87         459 :     void ResetReading() override
      88             :     {
      89         459 :         Init();
      90         459 :         OGRMemLayer::ResetReading();
      91         459 :     }
      92             : 
      93             :     int TestCapability(const char *pszCap) const override;
      94             : 
      95          84 :     const CPLString &GetFilename() const
      96             :     {
      97          84 :         return osFilename;
      98             :     }
      99             : 
     100             :     /* For external usage. Mess with FID */
     101             :     OGRFeature *GetNextFeature() override;
     102             :     OGRFeature *GetFeature(GIntBig nFeatureId) override;
     103             :     OGRErr ISetFeature(OGRFeature *poFeature) override;
     104             :     OGRErr ISetFeatureUniqPtr(std::unique_ptr<OGRFeature> poFeature) override;
     105             :     OGRErr IUpdateFeature(OGRFeature *poFeature, int nUpdatedFieldsCount,
     106             :                           const int *panUpdatedFieldsIdx,
     107             :                           int nUpdatedGeomFieldsCount,
     108             :                           const int *panUpdatedGeomFieldsIdx,
     109             :                           bool bUpdateStyleString) override;
     110             :     OGRErr DeleteFeature(GIntBig nFID) override;
     111             : 
     112          23 :     OGRErr SetNextByIndex(GIntBig nIndex) override
     113             :     {
     114          23 :         Init();
     115          23 :         return OGRMemLayer::SetNextByIndex(nIndex);
     116             :     }
     117             : 
     118             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     119             :     OGRErr ICreateFeatureUniqPtr(std::unique_ptr<OGRFeature> poFeature,
     120             :                                  GIntBig *pnFID) override;
     121             : 
     122        5241 :     const OGRFeatureDefn *GetLayerDefn() const override
     123             :     {
     124        5241 :         const_cast<OGRXLSXLayer *>(this)->Init();
     125        5241 :         return OGRMemLayer::GetLayerDefn();
     126             :     }
     127             : 
     128         164 :     GIntBig GetFeatureCount(int bForce) override
     129             :     {
     130         164 :         Init();
     131         164 :         return OGRMemLayer::GetFeatureCount(bForce);
     132             :     }
     133             : 
     134             :     virtual OGRErr CreateField(const OGRFieldDefn *poField,
     135             :                                int bApproxOK = TRUE) override;
     136             : 
     137           0 :     OGRErr DeleteField(int iField) override
     138             :     {
     139           0 :         Init();
     140           0 :         SetUpdated();
     141           0 :         return OGRMemLayer::DeleteField(iField);
     142             :     }
     143             : 
     144           0 :     OGRErr ReorderFields(int *panMap) override
     145             :     {
     146           0 :         Init();
     147           0 :         SetUpdated();
     148           0 :         return OGRMemLayer::ReorderFields(panMap);
     149             :     }
     150             : 
     151          18 :     virtual OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
     152             :                                   int nFlagsIn) override
     153             :     {
     154          18 :         Init();
     155          18 :         SetUpdated();
     156          18 :         return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
     157             :     }
     158             : 
     159           4 :     const std::string &GetCols() const
     160             :     {
     161           4 :         return m_osCols;
     162             :     }
     163             : 
     164             :     OGRErr SyncToDisk() override;
     165             : 
     166             :     GDALDataset *GetDataset() override;
     167             : };
     168             : 
     169             : /************************************************************************/
     170             : /*                           OGRXLSXDataSource                          */
     171             : /************************************************************************/
     172             : #define STACK_SIZE 5
     173             : 
     174             : typedef enum
     175             : {
     176             :     STATE_DEFAULT,
     177             : 
     178             :     /* for sharedString.xml */
     179             :     STATE_SI,
     180             :     STATE_T,
     181             : 
     182             :     /* for sheet?.xml */
     183             :     STATE_COLS,
     184             :     STATE_SHEETDATA,
     185             :     STATE_ROW,
     186             :     STATE_CELL,
     187             :     STATE_TEXTV,
     188             : } HandlerStateEnum;
     189             : 
     190             : typedef struct
     191             : {
     192             :     HandlerStateEnum eVal;
     193             :     int nBeginDepth;
     194             : } HandlerState;
     195             : 
     196             : class XLSXFieldTypeExtended
     197             : {
     198             :   public:
     199             :     OGRFieldType eType;
     200             :     bool bHasMS;
     201             : 
     202         176 :     XLSXFieldTypeExtended() : eType(OFTMaxType), bHasMS(false)
     203             :     {
     204         176 :     }
     205             : 
     206         395 :     explicit XLSXFieldTypeExtended(OGRFieldType eTypeIn, bool bHasMSIn = false)
     207         395 :         : eType(eTypeIn), bHasMS(bHasMSIn)
     208             :     {
     209         395 :     }
     210             : };
     211             : 
     212             : class OGRXLSXDataSource final : public GDALDataset
     213             : {
     214             :     char *pszName;
     215             :     CPLString osPrefixedFilename;
     216             :     bool bUpdatable;
     217             :     bool bUpdated;
     218             : 
     219             :     int nLayers;
     220             :     OGRXLSXLayer **papoLayers;
     221             :     std::map<CPLString, CPLString> oMapRelsIdToTarget;
     222             :     std::set<std::string> m_oSetSheetId;
     223             : 
     224             :     void AnalyseSharedStrings(VSILFILE *fpSharedStrings);
     225             :     void AnalyseWorkbook(VSILFILE *fpWorkbook);
     226             :     void AnalyseWorkbookRels(VSILFILE *fpWorkbookRels);
     227             :     void AnalyseStyles(VSILFILE *fpStyles);
     228             : 
     229             :     std::vector<std::string> apoSharedStrings;
     230             :     std::string osCurrentString;
     231             : 
     232             :     bool bFirstLineIsHeaders;
     233             :     int bAutodetectTypes;
     234             : 
     235             :     XML_Parser oParser;
     236             :     bool bStopParsing;
     237             :     int nWithoutEventCounter;
     238             :     int nDataHandlerCounter;
     239             :     int nCurLine;
     240             :     int nCurCol;
     241             : 
     242             :     OGRXLSXLayer *poCurLayer;
     243             :     std::string m_osCols{};
     244             : 
     245             :     int nStackDepth;
     246             :     int nDepth;
     247             :     HandlerState stateStack[STACK_SIZE];
     248             : 
     249             :     CPLString osValueType;
     250             :     CPLString osValue;
     251             : 
     252             :     std::vector<std::string> apoFirstLineValues;
     253             :     std::vector<std::string> apoFirstLineTypes;
     254             :     std::vector<std::string> apoCurLineValues;
     255             :     std::vector<std::string> apoCurLineTypes;
     256             : 
     257             :     bool bInCellXFS;
     258             :     std::map<int, XLSXFieldTypeExtended> apoMapStyleFormats;
     259             :     std::vector<XLSXFieldTypeExtended> apoStyles;
     260             : 
     261             :     void PushState(HandlerStateEnum eVal);
     262             :     void startElementDefault(const char *pszName, const char **ppszAttr);
     263             :     void startElementTable(const char *pszName, const char **ppszAttr);
     264             :     void endElementTable(const char *pszName);
     265             :     void startElementCols(const char *pszName, const char **ppszAttr);
     266             :     void endElementCols(const char *pszName);
     267             :     void startElementRow(const char *pszName, const char **ppszAttr);
     268             :     void endElementRow(const char *pszName);
     269             :     void startElementCell(const char *pszName, const char **ppszAttr);
     270             :     void endElementCell(const char *pszName);
     271             :     void dataHandlerTextV(const char *data, int nLen);
     272             : 
     273             :     void DetectHeaderLine();
     274             : 
     275             :     OGRFieldType GetOGRFieldType(const char *pszValue, const char *pszValueType,
     276             :                                  OGRFieldSubType &eSubType);
     277             : 
     278             :     void DeleteLayer(const char *pszLayerName);
     279             : 
     280             :   public:
     281             :     explicit OGRXLSXDataSource(CSLConstList papszOpenOptionsIn);
     282             :     ~OGRXLSXDataSource() override;
     283             :     CPLErr Close(GDALProgressFunc = nullptr, void * = nullptr) override;
     284             : 
     285             :     int Open(const char *pszFilename, const char *pszPrefixedFilename,
     286             :              VSILFILE *fpWorkbook, VSILFILE *fpWorkbookRels,
     287             :              VSILFILE *fpSharedStrings, VSILFILE *fpStyles, int bUpdate);
     288             :     int Create(const char *pszName, char **papszOptions);
     289             : 
     290             :     int GetLayerCount() const override;
     291             :     const OGRLayer *GetLayer(int) const override;
     292             : 
     293             :     int TestCapability(const char *) const override;
     294             : 
     295             :     OGRLayer *ICreateLayer(const char *pszName,
     296             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     297             :                            CSLConstList papszOptions) override;
     298             : 
     299             :     OGRErr DeleteLayer(int iLayer) override;
     300             : 
     301             :     CPLErr FlushCache(bool bAtClosing) override;
     302             : 
     303             :     void startElementCbk(const char *pszName, const char **ppszAttr);
     304             :     void endElementCbk(const char *pszName);
     305             :     void dataHandlerCbk(const char *data, int nLen);
     306             : 
     307             :     void startElementSSCbk(const char *pszName, const char **ppszAttr);
     308             :     void endElementSSCbk(const char *pszName);
     309             :     void dataHandlerSSCbk(const char *data, int nLen);
     310             : 
     311             :     void startElementWBRelsCbk(const char *pszName, const char **ppszAttr);
     312             : 
     313             :     void startElementWBCbk(const char *pszName, const char **ppszAttr);
     314             : 
     315             :     void startElementStylesCbk(const char *pszName, const char **ppszAttr);
     316             :     void endElementStylesCbk(const char *pszName);
     317             : 
     318             :     void BuildLayer(OGRXLSXLayer *poLayer);
     319             : 
     320        1202 :     bool GetUpdatable()
     321             :     {
     322        1202 :         return bUpdatable;
     323             :     }
     324             : 
     325          12 :     void SetUpdated()
     326             :     {
     327          12 :         bUpdated = true;
     328          12 :     }
     329             : };
     330             : 
     331             : }  // namespace OGRXLSX
     332             : 
     333             : #endif /* ndef OGR_XLSX_H_INCLUDED */

Generated by: LCOV version 1.14