很多时候,尤其是游戏开发中,策划往往将文档,数据等写入excel中,程序,需要通过各种方式解析excel,让程序可以读。
常见的方案有:
1.将excel转换为csv,逗号分割方式,程序通过split逗号按照特定格式进行转换。(功能不够强大,格式要求很严,无法灵活配置很多特殊的功能)
2.将excel转换为lua table。这是C++游戏开发的常用方式。 (无法通过c++对象序列化为excel)
3.将excel转换到数据库的table中。类似方案2,不同的是,这里是转换到数据库的表中。 (无法通过c++对象序列化为excel)
4.将excel转换为xml格式,然后通过如,java中simple_xml等支持xml序列化和反序列化的框架,进行序列化和反许序列化。
5....
为什么要这样做。游戏开发中,首先要明确一点,当一个功能要开发的时候,首先不是策划配表,而是程序先按照大致的方案,创建对应的对象数据,有了对象,类型,将该类型进行序列化为.xml然后,策划按照该.xml格式添加配置,每当有新的功能要添加时,程序在原有的类型的基础上添加新的类型,读取原来的xml,通过新的类型,重新生成xml文件,然后,策划仅仅添加新增的属性,在这种情况下,程序的改动就非常少,关注的点,也仅仅在新增的属性上。
我们编写序列化的简单例子:
/** * Created by Administrator on 13-12-25. */ package main import ( "fmt" "os" "reflect" "encoding/xml" ) var xmlHead []byte = []byte("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><?mso-application progid=\"Excel.Sheet\"?>") type Workbook struct { Xmlns string `xml:"Xmlns,attr"` Xmlns_o string `xml:"xmlns:o,attr"` Xmlns_x string `xml:"xmlns:x,attr"` Xmlns_ss string `xml:"xmlns:ss,attr"` Xmlns_html string `xml:"xmlns:html,attr"` Xmlns_dt string `xml:"xmlns:dt,attr"` Worksheets []Worksheet `xml:"Worksheet"` } func newWorkbook() *Workbook { return &Workbook{ Xmlns:"urn:schemas-microsoft-com:office:spreadsheet", Xmlns_o:"urn:schemas-microsoft-com:office:office", Xmlns_x:"urn:schemas-microsoft-com:office:excel", Xmlns_ss:"urn:schemas-microsoft-com:office:spreadsheet", Xmlns_html:"http://www.w3.org/TR/REC-html40", Xmlns_dt:"uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"} } type Worksheet struct { Name string `xml:"ss:Name,attr"` Table Table `xml:"Table"` } type Table struct { ExpandedColumnCount int `xml:"ss:ExpandedColumnCount,attr"` // 属性数量 ExpandedRowCount int `xml:"ss:ExpandedRowCount,attr"` // 数据条数 FullColumns int `xml:"x:FullColumns,attr"` FullRows int `xml:"x:FullRows,attr"` DefaultColumnWidth float32 `xml:"ss:DefaultColumnWidth,attr"` DefaultRowHeight float32 `xml:"ss:DefaultRowHeight,attr"` Rows []Row `xml:"Row"` } func newTable(columnCount, rowCount int) *Table { return &Table{ ExpandedColumnCount:columnCount, ExpandedRowCount:rowCount, FullColumns:1, FullRows:1, DefaultColumnWidth:60, DefaultRowHeight:16} } type Row struct { Cells []Cell `xml:"Cell"` } type Cell struct { Data Data `xml:"Data"` } type Data struct { Type string `xml:"ss:Type,attr"` Value interface{} `xml:",chardata"` } func newCell(_type string, _value interface{}) Cell { data := Data{Type: _type, Value: _value} cell := Cell{Data: data} return cell } func MarshalExcelXml(arr []interface {}) { var name string = "unknow" book := newWorkbook() sheet := Worksheet{} columnCount, rowCount := 0, len(arr) for _, v := range arr { if v != nil { t := reflect.TypeOf(v) name = t.Name()+"s" columnCount = t.NumField() break } } fmt.Fprintf(os.Stdout, "name %s columnCount %d, rowCount %d\n", name, columnCount, rowCount) if columnCount > 0 && rowCount > 0 { table := newTable(columnCount, rowCount) fmt.Fprintf(os.Stdout, "table %v\n", table) rows := make([]Row, rowCount) for index := 0; index < rowCount; index++ { fmt.Fprintf(os.Stdout, "index = %d v = %v\n", index, arr[index]) if arr[index] != nil { val := reflect.ValueOf(arr[index]) cells := make([]Cell, columnCount) for i := 0; i < columnCount; i++ { fieldValue := val.Field(i) fmt.Fprintf(os.Stdout, "fieldValue %v Type %v \n", fieldValue, fieldValue.Type()) var cell Cell switch fieldValue.Kind() { case reflect.Int: cell = newCell("Number", fieldValue.Int()) case reflect.String: cell = newCell("String", fieldValue.String()) } cells[i] = cell } rows[index].Cells = cells } } table.Rows = rows sheet.Name = "tasks" sheet.Table = *table book.Worksheets = make([]Worksheet, 1) book.Worksheets[0] = sheet f, err := os.OpenFile("c:/"+name+".xml", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModeAppend) defer f.Close() if err != nil { fmt.Fprintf(os.Stderr, "error : %s", err.Error()) return } n, err := f.Write(xmlHead) if err == nil && n < len(xmlHead) { fmt.Fprintf(os.Stderr, "error : write Fail") return } buf, err := xml.Marshal(book) if err != nil { fmt.Fprintf(os.Stderr, "error : %s", err.Error()) return } n, err = f.Write(buf) if err == nil && n < len(buf) { fmt.Fprintf(os.Stderr, "error : write Fail") return } } } type Task struct{ Id int Name string Name1 string } func main() { tasks := []interface{}{Task{1, "t1", "t1_1"}, Task{2, "t2", "t2_1"}, Task{3, "t3", "t3_1"}} MarshalExcelXml(tasks) }
生成的.xml文件:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><?mso-application progid="Excel.Sheet"?> <Workbook Xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"> <Worksheet ss:Name="tasks"> <Table ss:ExpandedColumnCount="3" ss:ExpandedRowCount="3" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="60" ss:DefaultRowHeight="16"> <Row> <Cell> <Data ss:Type="Number">1</Data> </Cell> <Cell> <Data ss:Type="String">t1</Data> </Cell> <Cell> <Data ss:Type="String">t1_1</Data> </Cell> </Row> <Row> <Cell> <Data ss:Type="Number">2</Data> </Cell> <Cell> <Data ss:Type="String">t2</Data> </Cell> <Cell> <Data ss:Type="String">t2_1</Data> </Cell> </Row> <Row> <Cell> <Data ss:Type="Number">3</Data> </Cell> <Cell> <Data ss:Type="String">t3</Data> </Cell> <Cell> <Data ss:Type="String">t3_1</Data> </Cell> </Row> </Table> </Worksheet> </Workbook>
直接通过excel打开:
1 | t1 | t1_1 |
2 | t2 | t2_1 |
3 | t3 | t3_1 |
转载请注明出处:
http://blog.csdn.net/eclipser1987/article/details/17691745
有疑问加站长微信联系(非本文作者)