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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM