很多时候,尤其是游戏开发中,策划往往将文档,数据等写入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("")
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文件:
1
|
t1
|
t1_1
|
2
|
t2
|
t2_1
|
3
|
t3
|
t3_1
|
1 | t1 | t1_1 |
2 | t2 | t2_1 |
3 | t3 | t3_1 |
转载请注明出处:
http://blog.csdn.net/eclipser1987/article/details/17691745