zoukankan      html  css  js  c++  java
  • c++ 读取并解析excel文件方法

    用Cocos开发模型特效工具编辑器,跨Mac和windows,当中有个需求是读取并解析excel文件,但网上的查找的例子几乎都只能是在windows下面使用,再或者是命令行脚本之类的。于是,自己写了一个非常轻量级的excel解析代码,纯cpp,除了依赖几个cocos2d 方法(zip解压和tinyxml2解析库),不依赖任何系统API。  目前只能解析常见的表式结构(如果把excel当成word文档使用就别看下面了),分享给大家,

    如转发还请注明出处,感谢。

    为了保证mac和windows都可以跑过,所以去掉注释,原谅我是VS菜鸟,当然代码够简单不写也能看懂。

    getSheetArray返回的是excel的 行数组 ,因为c++里面难以实现动态类结构,所以不得已写成这种方式,一般情况下该数据拿到后需要二次加工,你可以拿一个简单的excel表格(比如道具物品表),测试打个断点就知道有哪些数据结构。 我还有一个纯js版本的,适合cocos2d-js使用,待日后完善了再丢出来。

    //
    //  Excel.h
    //  基于com.lipi.excel as3 版本设计,感谢lipi的源码参考
    //  Created by howe on 15/5/5.
    //    auto excel =  new Excel();
    //    bool result = excel->parseExcelFile(filepath, 1);
    //    std::vector<LineInfo> arr = std::move( excel->getSheetArray() );
    //
    
    #ifndef __ModelEditor__Excel__
    #define __ModelEditor__Excel__
    
    #include <stdio.h>
    #include <vector>
    #include <map>
    
    
    struct LineInfo
    {
        int lineIndex;
        std::vector<std::string> array;
    };
    
    class Excel
    {
    public:
        Excel();
        
        bool parseExcelFile(const std::string &filepath,int sheetIndex);
        
        std::vector<LineInfo> getSheetArray();
        
    private:
        std::vector<std::string> _getValueArray();
    private:
        std::map<int,LineInfo> excelHash;
        std::string _excelFilePath;
    };
    
    #endif /* defined(__ModelEditor__Excel__) */
    

     Excel.cpp 实现部分

    //
    //  Excel.cpp
    //
    //  Created by howe on 15/5/5.
    //  
    //
    
    #include <iostream>
    #include <string>
    
    #include "Excel.h"
    #include "cocos2d.h"
    
    #include "external/tinyxml2/tinyxml2.h"
    
    using namespace tinyxml2;
    using namespace std;
    
    unsigned char* getFileDataFromZip(const std::string& zipFilePath, const std::string& filename, ssize_t *size)
    {
        return cocos2d::FileUtils::getInstance()->getFileDataFromZip(zipFilePath, filename, size);
    }
    
    void deleteNum( std::string &content)
    {
        string::iterator t = content.begin();
        while(t != content.end())
        {
            if(*t >= '0' && *t <= '9')
            {
               content.erase(t);
            }
            else
            {
                t++;
            }
        }
    }
    int getColIndex(std::string &content)
    {
        auto returnValue = 0;
        for (auto i =0; i < content.length(); i++)
        {
            char n = content[i];
            auto cValue = n - 64;
            returnValue *= 26;
            returnValue += cValue;
        }
        return returnValue - 1;
    }
    
    Excel::Excel()
    :_excelFilePath("")
    {
        
    }
    
    bool Excel::parseExcelFile(const std::string &ilepath, int sheetIndex)
    {
        _excelFilePath = ilepath;
        excelHash.clear();
        
        char xml_file[256] = {0};
        sprintf(xml_file, "xl/worksheets/sheet%d.xml",sheetIndex+1);
        ssize_t size;
        
        auto fileData = getFileDataFromZip(_excelFilePath, xml_file, &size);
        if (!fileData)
        {
            CCLOG(ilepath.c_str(), "The excel file is not exist!");
            return false;
        }
        auto valueArray = std::move(_getValueArray());
    
        tinyxml2::XMLDocument doc;
    
        doc.Parse((const char*)fileData,size);
        
        XMLElement *root = doc.RootElement();
        
        XMLElement * sheetDataElement = root->FirstChildElement("sheetData");
        XMLElement * rowElement =sheetDataElement->FirstChildElement("row");
        
        while (rowElement)
        {
            LineInfo lineInfo;
            auto rowIndex = atoi(rowElement->Attribute("r")) - 1;
            lineInfo.lineIndex = rowIndex;
            std::vector<std::string> &rowArray = lineInfo.array;
            auto cElement = rowElement->FirstChildElement("c");
            while (cElement)
            {
                std::string cc = cElement->Attribute("r");
                deleteNum(cc);
                auto colIndex  = getColIndex( cc );
                std::string t = "";
                std::string v = "";
    
                if (cElement->Attribute("t"))
                {
                    t = cElement->Attribute("t");
                }
                auto vElement = cElement->FirstChildElement("v");
                if (vElement)
                {
                    v = vElement->GetText();
                }
                if (rowArray.size() < colIndex)
                {
                    int len = rowArray.size();
                    for (auto i = 0;i < colIndex - len;i++)
                    {
                        rowArray.push_back(""); //
                    }
                }
                if (t == "s")
                {
                    rowArray.push_back(valueArray[atoi(v.c_str())]);
                }
                else
                {
                    rowArray.push_back(v);
                }
                cElement = cElement->NextSiblingElement("c");
            }
            auto bb = false;
            for (auto iii : rowArray)
            {
                if (iii.length() > 1)
                {
                    bb = true;
                    break;
                }
            }
            if (bb)
            {
                excelHash[rowIndex] = lineInfo;
            }
            rowElement = rowElement->NextSiblingElement("row");
        }
        return true;
    }
    
    std::vector<std::string> Excel::_getValueArray()
    {
        std::vector<std::string> result;
        
        ssize_t size;
        auto fileData = getFileDataFromZip(_excelFilePath,  "xl/sharedStrings.xml", &size);
        
        tinyxml2::XMLDocument doc;
        doc.Parse((const char*)fileData,size);
        XMLElement *root = doc.RootElement();
        XMLElement *siElement = root->FirstChildElement("si");
        
        while (siElement)
        {
            std::string temp = "";
            auto tElement = siElement->FirstChildElement("t");
            while (tElement)
            {
                temp = temp + tElement->GetText();
                tElement = tElement->NextSiblingElement("t");
            }
            result.push_back(temp);
            siElement = siElement->NextSiblingElement("si");
        }
        return result;
    }
    
    std::vector<LineInfo> Excel::getSheetArray()
    {
        std::vector<LineInfo> result;
        for ( auto ite = excelHash.begin();ite != excelHash.end();ite++)
        {
            auto &lineInfo_ = ite->second;
            result.push_back(lineInfo_);
        }
        return result;
    }
    
  • 相关阅读:
    调用DirectX进行简单的多媒体编程系列(一)
    C#中编写sqlserver中自定义函数,实现复杂报表
    学习笔记:javascript定义类的过程(类一词是形象说法,javascript中并没有类一词)
    HttpModule与HttpHandler详解 (转)
    asp.net运行原理(转)
    最近项目报表开发中写的存储过程学生综合成绩对比
    调用DirectX进行简单的多媒体编程系列(四)
    清欠率(存储过程)
    ExtJS中的面向对象设计,组件化编程思想
    ExtJS中如何扩展自定义的类
  • 原文地址:https://www.cnblogs.com/howeho/p/4533009.html
Copyright © 2011-2022 走看看