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;

}

 

你可能感兴趣的:(Excel)