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;
}

 

posted @ 2015-05-27 11:41  haroel  阅读(26908)  评论(2编辑  收藏  举报