用Golang助力表妹轻松实现自动化办公!(完整代码附后)
Hello,大家好,我是lbbniu~
今天有一个有趣的编程需求要分享,这次的灵感来源于我可爱的表妹。简单来说,我们将利用Golang对Excel文件进行批量处理,达到高效自动化办公的目的。
一、具体需求
手上有一系列N个表格,每个表格都有相同的结构,看起来就像这样:
任务是将所有表中的数据汇总,按照每个人的得分和积分进行合计,然后按总积分排名。在总积分相同的情况下,名次也相同但不是连续的排序。如果总积分和名次都相同,再按总得分降序展示,但不改变排名。
结果如下图所示:
二、Golang开发
首先,让我们引入需要的包:
package main
import (
"fmt"
"log"
"path/filepath"
"sort"
"github.com/tealeg/xlsx"
)
接下来,获取所有Excel文件的路径:
func getExcelFiles() []string {
files, err := filepath.Glob("./样例数据/*.xlsx")
if err != nil {
log.Fatal(err)
}
return files
}
然后,将各表数据合并到主结构体:
// Record 结构体表示每个人的记录
type Record struct {
Name string
Monthly int
Points int
Ranking int
}
func getCellValue(cell *xlsx.Cell) int {
value, err := cell.Int()
if err != nil {
log.Fatal(err)
}
return value
}
func mergeData(files []string) []Record {
var mergedData []Record
for _, file := range files {
// 读取Excel文件
xlFile, err := xlsx.OpenFile(file)
if err != nil {
log.Fatal(err)
}
// 处理每个Sheet
for _, sheet := range xlFile.Sheets {
for _, row := range sheet.Rows[2:] {
record := Record{
Name: row.Cells[0].String(),
Monthly: getCellValue(row.Cells[1]),
Points: getCellValue(row.Cells[3]),
}
mergedData = append(mergedData, record)
}
}
}
return mergedData
}
接下来,计算总积分和总排名:
func calculateTotalAndRanking(data []Record) []Record {
totalMonthlys := make(map[string]int)
totalPoints := make(map[string]int)
uniqueNames := make(map[string]bool)
var mergedRecords []Record
for _, record := range data {
uniqueNames[record.Name] = true
totalMonthlys[record.Name] += record.Monthly
totalPoints[record.Name] += record.Points
}
sortedNames := make([]string, 0, len(uniqueNames))
for name := range uniqueNames {
sortedNames = append(sortedNames, name)
}
sort.Slice(sortedNames, func(i, j int) bool {
if totalPoints[sortedNames[i]] == totalPoints[sortedNames[j]] {
return sortedNames[i] < sortedNames[j]
}
return totalPoints[sortedNames[i]] > totalPoints[sortedNames[j]]
})
for _, record := range data {
if _, ok := uniqueNames[record.Name]; ok {
mergedRecord := Record{
Name: record.Name,
Monthly: totalMonthlys[record.Name],
Points: totalPoints[record.Name],
}
mergedRecords = append(mergedRecords, mergedRecord)
delete(uniqueNames, record.Name) // 避免重复计算相同姓名的记录
}
}
return mergedRecords
}
最后,按总积分和总得分排序,输出结果:
func sortAndOutputResults(data []Record) {
sort.Slice(data, func(i, j int) bool {
if data[i].Points == data[j].Points {
return data[i].Monthly > data[j].Monthly
}
return data[i].Points > data[j].Points
})
outputFile := "总积分及排名.xlsx"
xlFile := xlsx.NewFile()
sheet, err := xlFile.AddSheet("Sorted Results")
if err != nil {
log.Fatal(err)
}
row := sheet.AddRow()
row.AddCell().Value = "姓名"
row.AddCell().Value = "总得分"
row.AddCell().Value = "总积分"
row.AddCell().Value = "总排名"
ranking, points := 1, data[0].Points
for _, record := range data {
if points != record.Points {
ranking++
}
row := sheet.AddRow()
row.AddCell().Value = record.Name
row.AddCell().SetInt(record.Monthly)
row.AddCell().SetInt(record.Points)
row.AddCell().SetInt(ranking)
}
if err := xlFile.Save(outputFile); err != nil {
log.Fatal(err)
}
fmt.Printf("排序后的结果已保存到 %s\n", outputFile)
}
func main() {
excelFiles := getExcelFiles()
mergedData := mergeData(excelFiles)
calculateTotalAndRanking(mergedData)
sortAndOutputResults(mergedData)
}
完整代码:
package main
import (
"fmt"
"log"
"path/filepath"
"sort"
"github.com/tealeg/xlsx"
)
// Record 结构体表示每个人的记录
type Record struct {
Name string
Monthly int
Points int
Ranking int
}
func getCellValue(cell *xlsx.Cell) int {
value, err := cell.Int()
if err != nil {
log.Fatal(err)
}
return value
}
func getExcelFiles() []string {
files, err := filepath.Glob("./样例数据/*.xlsx")
if err != nil {
log.Fatal(err)
}
return files
}
func mergeData(files []string) []Record {
var mergedData []Record
for _, file := range files {
// 读取Excel文件
xlFile, err := xlsx.OpenFile(file)
if err != nil {
log.Fatal(err)
}
// 处理每个Sheet
for _, sheet := range xlFile.Sheets {
for _, row := range sheet.Rows[2:] {
record := Record{
Name: row.Cells[0].String(),
Monthly: getCellValue(row.Cells[1]),
Points: getCellValue(row.Cells[3]),
}
mergedData = append(mergedData, record)
}
}
}
return mergedData
}
func calculateTotalAndRanking(data []Record) []Record {
totalMonthlys := make(map[string]int)
totalPoints := make(map[string]int)
uniqueNames := make(map[string]bool)
var mergedRecords []Record
for _, record := range data {
uniqueNames[record.Name] = true
totalMonthlys[record.Name] += record.Monthly
totalPoints[record.Name] += record.Points
}
sortedNames := make([]string, 0, len(uniqueNames))
for name := range uniqueNames {
sortedNames = append(sortedNames, name)
}
sort.Slice(sortedNames, func(i, j int) bool {
if totalPoints[sortedNames[i]] == totalPoints[sortedNames[j]] {
return sortedNames[i] < sortedNames[j]
}
return totalPoints[sortedNames[i]] > totalPoints[sortedNames[j]]
})
for _, record := range data {
if _, ok := uniqueNames[record.Name]; ok {
mergedRecord := Record{
Name: record.Name,
Monthly: totalMonthlys[record.Name],
Points: totalPoints[record.Name],
}
mergedRecords = append(mergedRecords, mergedRecord)
delete(uniqueNames, record.Name) // 避免重复计算相同姓名的记录
}
}
return mergedRecords
}
func sortAndOutputResults(data []Record) {
sort.Slice(data, func(i, j int) bool {
if data[i].Points == data[j].Points {
return data[i].Monthly > data[j].Monthly
}
return data[i].Points > data[j].Points
})
outputFile := "总积分及排名.xlsx"
xlFile := xlsx.NewFile()
sheet, err := xlFile.AddSheet("Sorted Results")
if err != nil {
log.Fatal(err)
}
row := sheet.AddRow()
row.AddCell().Value = "姓名"
row.AddCell().Value = "总得分"
row.AddCell().Value = "总积分"
row.AddCell().Value = "总排名"
ranking, points := 1, data[0].Points
for _, record := range data {
if points != record.Points {
ranking++
}
row := sheet.AddRow()
row.AddCell().Value = record.Name
row.AddCell().SetInt(record.Monthly)
row.AddCell().SetInt(record.Points)
row.AddCell().SetInt(ranking)
}
if err := xlFile.Save(outputFile); err != nil {
log.Fatal(err)
}
fmt.Printf("排序后的结果已保存到 %s\n", outputFile)
}
func main() {
excelFiles := getExcelFiles()
mergedData := mergeData(excelFiles)
mergedData = calculateTotalAndRanking(mergedData)
sortAndOutputResults(mergedData)
}
以上就是整个Golang实现的简要流程。虽然代码比较简洁,但相信这会为表妹省去不少时间,嘿嘿!
希望大家也能将Golang这个强大的语言用于工作和生活,提高工作效率,让生活更有趣。
关注我的公众号,后台回复“每天进步一点点”,即可获取完整代码和数据哦!
感谢阅读,我们下期见!
lbbniu 敬上
关注我,共同进步!