文档:https://xuri.me/excelize/zh-hans/cell.html?q=
读取本地文件与文件流:https://blog.csdn.net/qq_41119959/article/details/122128547
excel文件流批量插入实例
const (
ExcelTitle_Phone = "手机号"
ExcelTitle_Name = "姓名"
ExcelTitle_Place = "位置"
)
func CreateInBatches(devId int, file *multipart.FileHeader) error {
var (
wg sync.WaitGroup
)
// 1.处理参数
// 2.为文件提供阅读器(将保存在内存中)
excelFile, err := file.Open()
if err != nil {
return err
}
// 3.流式读取(默认读取第一个sheet),返回所有的单元格内容
rows, err := utils.ReadExcelFile(excelFile)
if err != nil {
return err
}
// 4.初始化一个map
// 存放excel的对应内容及其索引,例如 手机号:0,代表第一列为手机号
excelMap := make(map[string]int)
// 从excel中取出所有的标题及其索引
for i, key := range rows[0] {
excelMap[key] = i
}
// 判断标题除外的数据有多少行
valuelen := len(rows[1:])
// 每一千行为一批次,向上取整
batch := int(math.Ceil(float64(valuelen) / float64(1000)))
// 初始化一个map,记录每个批次的索引及其数据量
batchMap := make(map[int]int)
for i := 0; i < batch; i++ {
// 记录每一个批次对应的数据界限,例如 batchMap[0] = 1000 batchMap[1] = 2000
// 如果不足1000条就以具体的行数valuelen为底线
if batch == 1 || i == batch-1 {
// <= 1000 行数据 || 例如 5290 中的 290
batchMap[i] = valuelen
} else {
// > 1000 行数据
batchMap[i] = (i + 1) * 1000
}
wg.Add(1)
go func(i int, batchMap map[int]int) {
defer wg.Done()
var userScheduleList []schedule.UserSchedule
// 5.从excel中取出指定范围的所有的值
// 每次循环起点也需要变化,第一次为0,后面就是上一次的界限batchMap[i-1]
// 因为go没有三元表达式,用这个代替
startIndex := map[bool]int{true: 0, false: batchMap[i-1]}[i == 0]
// 因为切片[1:n]只能取到[1,n),所以需要给 batchMap[i]+1
for _, row := range rows[1+startIndex : batchMap[i]+1] {
user := schedule.UserSchedule{
// 从索引中取到各个标题对应的值
PhoneNum: row[excelMap[ExcelTitle_Phone]],
Name: row[excelMap[ExcelTitle_Name]],
Place: row[excelMap[ExcelTitle_Place]],
DevId: &devId,
}
userScheduleList = append(userScheduleList, user)
}
// 6.做数据库的批量插入操作
// 创建db
db := global.GVA_DB.Model(&schedule.UserSchedule{})
// 每次限制批量插入1000条
if err = db.CreateInBatches(userScheduleList, 1000).Error; err != nil {
// handle log
return
}
}(i,batchMap)
}
wg.Wait()
if err != nil {
return err
}
return nil
}
ReadExcelFile
func ReadExcelFile(file File, tableName ...string) ([][]string, error) {
f, err := excelize.OpenReader(file)
if err != nil {
return nil, err
}
//默认读取第一个
firstSheet := ""
if len(tableName) > 0 {
firstSheet = tableName[0]
} else {
firstSheet = f.GetSheetName(0)
}
rows, err := f.GetRows(firstSheet)
return rows, err
}