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: 2025-09-10 17:48:50 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 IUpdateFeature(OGRFeature *poFeature, int nUpdatedFieldsCount,
     105             :                           const int *panUpdatedFieldsIdx,
     106             :                           int nUpdatedGeomFieldsCount,
     107             :                           const int *panUpdatedGeomFieldsIdx,
     108             :                           bool bUpdateStyleString) override;
     109             :     OGRErr DeleteFeature(GIntBig nFID) override;
     110             : 
     111          23 :     OGRErr SetNextByIndex(GIntBig nIndex) override
     112             :     {
     113          23 :         Init();
     114          23 :         return OGRMemLayer::SetNextByIndex(nIndex);
     115             :     }
     116             : 
     117             :     OGRErr ICreateFeature(OGRFeature *poFeature) override;
     118             : 
     119        5241 :     const OGRFeatureDefn *GetLayerDefn() const override
     120             :     {
     121        5241 :         const_cast<OGRXLSXLayer *>(this)->Init();
     122        5241 :         return OGRMemLayer::GetLayerDefn();
     123             :     }
     124             : 
     125         164 :     GIntBig GetFeatureCount(int bForce) override
     126             :     {
     127         164 :         Init();
     128         164 :         return OGRMemLayer::GetFeatureCount(bForce);
     129             :     }
     130             : 
     131             :     virtual OGRErr CreateField(const OGRFieldDefn *poField,
     132             :                                int bApproxOK = TRUE) override;
     133             : 
     134           0 :     OGRErr DeleteField(int iField) override
     135             :     {
     136           0 :         Init();
     137           0 :         SetUpdated();
     138           0 :         return OGRMemLayer::DeleteField(iField);
     139             :     }
     140             : 
     141           0 :     OGRErr ReorderFields(int *panMap) override
     142             :     {
     143           0 :         Init();
     144           0 :         SetUpdated();
     145           0 :         return OGRMemLayer::ReorderFields(panMap);
     146             :     }
     147             : 
     148          18 :     virtual OGRErr AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
     149             :                                   int nFlagsIn) override
     150             :     {
     151          18 :         Init();
     152          18 :         SetUpdated();
     153          18 :         return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn);
     154             :     }
     155             : 
     156           4 :     const std::string &GetCols() const
     157             :     {
     158           4 :         return m_osCols;
     159             :     }
     160             : 
     161             :     OGRErr SyncToDisk() override;
     162             : 
     163             :     GDALDataset *GetDataset() override;
     164             : };
     165             : 
     166             : /************************************************************************/
     167             : /*                           OGRXLSXDataSource                          */
     168             : /************************************************************************/
     169             : #define STACK_SIZE 5
     170             : 
     171             : typedef enum
     172             : {
     173             :     STATE_DEFAULT,
     174             : 
     175             :     /* for sharedString.xml */
     176             :     STATE_SI,
     177             :     STATE_T,
     178             : 
     179             :     /* for sheet?.xml */
     180             :     STATE_COLS,
     181             :     STATE_SHEETDATA,
     182             :     STATE_ROW,
     183             :     STATE_CELL,
     184             :     STATE_TEXTV,
     185             : } HandlerStateEnum;
     186             : 
     187             : typedef struct
     188             : {
     189             :     HandlerStateEnum eVal;
     190             :     int nBeginDepth;
     191             : } HandlerState;
     192             : 
     193             : class XLSXFieldTypeExtended
     194             : {
     195             :   public:
     196             :     OGRFieldType eType;
     197             :     bool bHasMS;
     198             : 
     199         176 :     XLSXFieldTypeExtended() : eType(OFTMaxType), bHasMS(false)
     200             :     {
     201         176 :     }
     202             : 
     203         395 :     explicit XLSXFieldTypeExtended(OGRFieldType eTypeIn, bool bHasMSIn = false)
     204         395 :         : eType(eTypeIn), bHasMS(bHasMSIn)
     205             :     {
     206         395 :     }
     207             : };
     208             : 
     209             : class OGRXLSXDataSource final : public GDALDataset
     210             : {
     211             :     char *pszName;
     212             :     CPLString osPrefixedFilename;
     213             :     bool bUpdatable;
     214             :     bool bUpdated;
     215             : 
     216             :     int nLayers;
     217             :     OGRXLSXLayer **papoLayers;
     218             :     std::map<CPLString, CPLString> oMapRelsIdToTarget;
     219             :     std::set<std::string> m_oSetSheetId;
     220             : 
     221             :     void AnalyseSharedStrings(VSILFILE *fpSharedStrings);
     222             :     void AnalyseWorkbook(VSILFILE *fpWorkbook);
     223             :     void AnalyseWorkbookRels(VSILFILE *fpWorkbookRels);
     224             :     void AnalyseStyles(VSILFILE *fpStyles);
     225             : 
     226             :     std::vector<std::string> apoSharedStrings;
     227             :     std::string osCurrentString;
     228             : 
     229             :     bool bFirstLineIsHeaders;
     230             :     int bAutodetectTypes;
     231             : 
     232             :     XML_Parser oParser;
     233             :     bool bStopParsing;
     234             :     int nWithoutEventCounter;
     235             :     int nDataHandlerCounter;
     236             :     int nCurLine;
     237             :     int nCurCol;
     238             : 
     239             :     OGRXLSXLayer *poCurLayer;
     240             :     std::string m_osCols{};
     241             : 
     242             :     int nStackDepth;
     243             :     int nDepth;
     244             :     HandlerState stateStack[STACK_SIZE];
     245             : 
     246             :     CPLString osValueType;
     247             :     CPLString osValue;
     248             : 
     249             :     std::vector<std::string> apoFirstLineValues;
     250             :     std::vector<std::string> apoFirstLineTypes;
     251             :     std::vector<std::string> apoCurLineValues;
     252             :     std::vector<std::string> apoCurLineTypes;
     253             : 
     254             :     bool bInCellXFS;
     255             :     std::map<int, XLSXFieldTypeExtended> apoMapStyleFormats;
     256             :     std::vector<XLSXFieldTypeExtended> apoStyles;
     257             : 
     258             :     void PushState(HandlerStateEnum eVal);
     259             :     void startElementDefault(const char *pszName, const char **ppszAttr);
     260             :     void startElementTable(const char *pszName, const char **ppszAttr);
     261             :     void endElementTable(const char *pszName);
     262             :     void startElementCols(const char *pszName, const char **ppszAttr);
     263             :     void endElementCols(const char *pszName);
     264             :     void startElementRow(const char *pszName, const char **ppszAttr);
     265             :     void endElementRow(const char *pszName);
     266             :     void startElementCell(const char *pszName, const char **ppszAttr);
     267             :     void endElementCell(const char *pszName);
     268             :     void dataHandlerTextV(const char *data, int nLen);
     269             : 
     270             :     void DetectHeaderLine();
     271             : 
     272             :     OGRFieldType GetOGRFieldType(const char *pszValue, const char *pszValueType,
     273             :                                  OGRFieldSubType &eSubType);
     274             : 
     275             :     void DeleteLayer(const char *pszLayerName);
     276             : 
     277             :   public:
     278             :     explicit OGRXLSXDataSource(CSLConstList papszOpenOptionsIn);
     279             :     ~OGRXLSXDataSource() override;
     280             :     CPLErr Close() override;
     281             : 
     282             :     int Open(const char *pszFilename, const char *pszPrefixedFilename,
     283             :              VSILFILE *fpWorkbook, VSILFILE *fpWorkbookRels,
     284             :              VSILFILE *fpSharedStrings, VSILFILE *fpStyles, int bUpdate);
     285             :     int Create(const char *pszName, char **papszOptions);
     286             : 
     287             :     int GetLayerCount() const override;
     288             :     const OGRLayer *GetLayer(int) const override;
     289             : 
     290             :     int TestCapability(const char *) const override;
     291             : 
     292             :     OGRLayer *ICreateLayer(const char *pszName,
     293             :                            const OGRGeomFieldDefn *poGeomFieldDefn,
     294             :                            CSLConstList papszOptions) override;
     295             : 
     296             :     OGRErr DeleteLayer(int iLayer) override;
     297             : 
     298             :     CPLErr FlushCache(bool bAtClosing) override;
     299             : 
     300             :     void startElementCbk(const char *pszName, const char **ppszAttr);
     301             :     void endElementCbk(const char *pszName);
     302             :     void dataHandlerCbk(const char *data, int nLen);
     303             : 
     304             :     void startElementSSCbk(const char *pszName, const char **ppszAttr);
     305             :     void endElementSSCbk(const char *pszName);
     306             :     void dataHandlerSSCbk(const char *data, int nLen);
     307             : 
     308             :     void startElementWBRelsCbk(const char *pszName, const char **ppszAttr);
     309             : 
     310             :     void startElementWBCbk(const char *pszName, const char **ppszAttr);
     311             : 
     312             :     void startElementStylesCbk(const char *pszName, const char **ppszAttr);
     313             :     void endElementStylesCbk(const char *pszName);
     314             : 
     315             :     void BuildLayer(OGRXLSXLayer *poLayer);
     316             : 
     317        1202 :     bool GetUpdatable()
     318             :     {
     319        1202 :         return bUpdatable;
     320             :     }
     321             : 
     322          12 :     void SetUpdated()
     323             :     {
     324          12 :         bUpdated = true;
     325          12 :     }
     326             : };
     327             : 
     328             : }  // namespace OGRXLSX
     329             : 
     330             : #endif /* ndef OGR_XLSX_H_INCLUDED */

Generated by: LCOV version 1.14