// 解析a.b.c字段,由给定的msg找到这些字段病返回字段访问器 func makeCompactAccessor(fieldName string, inputMsg *data.DynamicMessage) (*data.DynamicMessage, *pbmeta.FieldDescriptor) { // 将路径按点分割 fieldNameList := strings.Split(fieldName, ".") msg := inputMsg for _, fieldName := range fieldNameList { // 这个路径对应的描述器 fd := msg.Desc.FieldByName(fieldName) if fd == nil { log.Errorf("field type name not found, %s in %s", fieldName, fieldName) return nil, nil } // 消息进行添加并迭代 if fd.Type() == pbprotos.FieldDescriptorProto_TYPE_MESSAGE { // 字段中带repeated message的不支持, 使用string2struct解析字段 fdmeta := data.GetFieldMeta(fd) if fd.IsRepeated() && fdmeta != nil && !fdmeta.String2Struct { log.Errorf("DO NOT support repeated message field, use 'string2struct' instead") return nil, nil } existMsg := msg.GetMessage(fd) if existMsg == nil { newMsg := data.NewDynamicMessage(fd.MessageDesc()) if !msg.SetMessage(fd, newMsg) { return nil, nil } msg = newMsg } else { msg = existMsg } } else { // 非消息返回当前层的反射器 return msg, fd } } // 纯消息, 字段使用父级 return msg, inputMsg.Desc.FieldByName(fieldName) }
func ValueConvetor(fd *pbmeta.FieldDescriptor, value string) (string, bool) { // 空单元格时, 给定一个这个类型对应的值 if value == "" { value = data.GetDefaultValue(fd) } switch fd.Type() { case pbprotos.FieldDescriptorProto_TYPE_FLOAT: _, err := strconv.ParseFloat(value, 32) if err != nil { return "", false } case pbprotos.FieldDescriptorProto_TYPE_INT64: _, err := strconv.ParseInt(value, 10, 64) if err != nil { return "", false } case pbprotos.FieldDescriptorProto_TYPE_UINT64: _, err := strconv.ParseUint(value, 10, 64) if err != nil { return "", false } case pbprotos.FieldDescriptorProto_TYPE_INT32: _, err := strconv.ParseInt(value, 10, 32) if err != nil { return "", false } case pbprotos.FieldDescriptorProto_TYPE_UINT32: _, err := strconv.ParseUint(value, 10, 32) if err != nil { return "", false } case pbprotos.FieldDescriptorProto_TYPE_BOOL: var final string for { if value == "是" { final = "true" break } else if value == "否" { final = "false" break } v, err := strconv.ParseBool(value) if err != nil { return "", false } if v { final = "true" } else { final = "false" } break } value = final case pbprotos.FieldDescriptorProto_TYPE_ENUM: ed := fd.EnumDesc() if ed.ValueCount() == 0 { return "", false } // 枚举值从表格读出时可能是中文枚举值, 需要根据meta信息转换为程序枚举值 var convValue string = value // 遍历这个枚举类型 for i := 0; i < ed.ValueCount(); i++ { evd := ed.Value(i) // 取出每个字段的meta meta := data.GetFieldMeta(evd) if meta == nil { continue } // 这个枚举值的别名是否与给定的一致 if meta.Alias == value { convValue = evd.Name() break } } if ed.ValueByName(convValue) == nil { log.Errorf("enum doesn't contain this value, %s in %s", convValue, fd.Name()) return "", false } value = convValue } return value, true }
func (self *Sheet) IterateData(callback func(*RecordInfo) bool) (*data.DynamicMessage, bool) { // 检查引导头 if !self.ParseProtoField() { return nil, true } // 是否继续读行 var readingLine bool = true // 检查引导Proto字段 sheetMsg, rowMsgDesc, lineFieldDesc := self.checkProtoHeader() if sheetMsg == nil { goto ErrorStop } // 遍历每一行 for self.cursor = DataIndex_DataBegin; readingLine; self.cursor++ { // 第一列是空的,结束 if self.GetCellData(self.cursor, 0) == "" { break } lineMsg := data.NewDynamicMessage(rowMsgDesc) if lineMsg == nil { break } // 遍历每一列 for self.index = 0; self.index < len(self.FieldHeader); self.index++ { ri := new(RecordInfo) // Proto字段头 ri.FieldName = self.FieldHeader[self.index] // 原始值 ri.Value = self.GetCellData(self.cursor, self.index) // #开头表示注释, 跳过 if strings.Index(ri.FieldName, "#") == 0 { continue } ri.FieldMsg, ri.FieldDesc = makeCompactAccessor(ri.FieldName, lineMsg) // 字段匹配错误 if ri.FieldMsg == nil || ri.FieldDesc == nil { goto ErrorStop } // 取扩展元信息 ri.FieldMeta = data.GetFieldMeta(ri.FieldDesc) if data.DebuggingLevel >= 1 { r, c := self.GetRC() log.Debugf("(%s) %s=%s", data.ConvR1C1toA1(r, c), ri.FieldName, ri.Value) } if !callback(ri) { goto ErrorStop } } sheetMsg.AddRepeatedMessage(lineFieldDesc, lineMsg) } return sheetMsg, true ErrorStop: r, c := self.GetRC() log.Errorf("%s|%s(%s)", self.file.FileName, self.Name, data.ConvR1C1toA1(r, c)) return nil, false }