func (self *Sheet) checkProtoHeader() (*data.DynamicMessage, *pbmeta.Descriptor, *pbmeta.FieldDescriptor) { // 指定的导出文件类型获得描述 fileDesc := self.file.descpool.MessageByFullName(self.header.ProtoTypeName) if fileDesc == nil { log.Errorf("can not found record descriptor, %s", self.header.ProtoTypeName) return nil, nil, nil } lineMsgDesc := fileDesc.FieldByName(self.header.RowFieldName) // 找不到定义 if lineMsgDesc == nil { log.Errorf("row field type not found: %s", self.header.RowFieldName) return nil, nil, nil } // 行描述类型必须是数组 if !lineMsgDesc.IsRepeated() { log.Errorf("row field type must be repeated type: %s", self.header.RowFieldName) return nil, nil, nil } // 根据描述创建输出文件消息及每一行的消息结构类型 return data.NewDynamicMessage(fileDesc), lineMsgDesc.MessageDesc(), lineMsgDesc }
// 解析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 (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 }