golang访问google sheet 写接口

如何访问google sheet、读接口详见
Golang访问Google Sheet

import (
	"bytes"
	"context"
	"fmt"
	"golang.org/x/oauth2/google"
	"google.golang.org/api/option"
	"google.golang.org/api/sheets/v4"
	"runtime/debug"
)

type UpdateGoogleSheetByRangeReq struct {
	Credentials   []byte
	SpreadsheetId string
	SheetName     string
	ExcelItemList interface{}
}

func UpdateGoogleSheetByRangeSrv(ctx context.Context, req *UpdateGoogleSheetByRangeReq) (wfmErr *wfmerror.WFMError) {
	defer func() {
		if p := recover(); p != nil {
			logger.LogErrorf("UpdateGoogleSheetByRangeReq panic=%v, stack=%v", p, string(debug.Stack()))
			wfmErr = constant.ErrCommonSystemUnknownErr.NewMessage(fmt.Sprintf("panic=%v", p))
		}
	}()
	// 解析密钥文件
	config, err := google.JWTConfigFromJSON(req.Credentials, sheets.SpreadsheetsScope)
	if err != nil {
		return constant.ErrCommonSystemUnknownErr.NewMessage(err.Error())
	}

	// 创建 Google Sheets 服务客户端
	client := config.Client(ctx)

	// 创建 Sheets 服务对象
	sheetsService, err := sheets.NewService(ctx, option.WithHTTPClient(client))
	if err != nil {
		return constant.ErrCommonSystemUnknownErr.NewMessage(err.Error())
	}

	data, rErr := readXLSX(req.ExcelItemList)
	if rErr != nil {
		return rErr.Mark()
	}
    
	exists, sErr := sheetExists(sheetsService, req.SpreadsheetId, req.SheetName)
	if sErr != nil {
		return sErr.Mark()
	}
	//不存在就创建,存在清除
	if exists {
		if cErr := clearSheet(sheetsService, req.SpreadsheetId, req.SheetName); cErr != nil {
			return cErr.Mark()
		}
	} else {
		if cErr := createSheet(sheetsService, req.SpreadsheetId, req.SheetName); cErr != nil {
			return cErr.Mark()
		}
	}

	// 使用 Sheets 服务对象进行操作
	readRange := fmt.Sprintf("%s!A1", req.SheetName)
	// 通过 Sheets 服务对象获取指定的工作表
	_, err = sheetsService.Spreadsheets.Values.Update(req.SpreadsheetId, readRange, &sheets.ValueRange{
		Values: data,
	}).ValueInputOption("RAW").Do()
	if err != nil {
		return constant.ErrCommonSystemUnknownErr.NewMessage(err.Error())
	}
	return nil
}

func readXLSX(ExcelItem interface{}) ([][]interface{}, *wfmerror.WFMError) {
	sheetName := "sheet1"
	//将ExcelItem转换为xlsx []byte
	fileData, _, gErr := excel.GenerateExcelBytes("excel.xlsx", []*dto.ExcelSheetTab{
		{
			SheetName: sheetName,
			Data:      ExcelItem,
		},
	})
	if gErr != nil {
		return nil, gErr.Mark()
	}

	f, err := excelize.OpenReader(bytes.NewReader(fileData))
	if err != nil {
		return nil, constant.ErrCommonSystemUnknownErr.NewMessage(err.Error())
	}

	rows, err := f.GetRows(sheetName) // 选择要读取的工作表
	if err != nil {
		return nil, constant.ErrCommonSystemUnknownErr.NewMessage(err.Error())
	}

	data := make([][]interface{}, len(rows))
	for i, row := range rows {
		data[i] = make([]interface{}, len(row))
		for j, cell := range row {
			data[i][j] = cell
		}
	}

	return data, nil
}

func sheetExists(srv *sheets.Service, spreadsheetId, sheetName string) (bool, *wfmerror.WFMError) {
	// 获取电子表格的结构
	spreadsheet, err := srv.Spreadsheets.Get(spreadsheetId).Do()
	if err != nil {
		return false, constant.ErrCommonSystemUnknownErr.NewMessage(err.Error())
	}

	// 检查工作表是否存在
	for _, sheet := range spreadsheet.Sheets {
		if sheet.Properties.Title == sheetName {
			return true, nil
		}
	}
	return false, nil
}

func createSheet(srv *sheets.Service, spreadsheetId, sheetName string) *wfmerror.WFMError {
	// 创建新的工作表
	requests := []*sheets.Request{
		{
			AddSheet: &sheets.AddSheetRequest{
				Properties: &sheets.SheetProperties{
					Title: sheetName,
				},
			},
		},
	}

	batchUpdateRequest := &sheets.BatchUpdateSpreadsheetRequest{
		Requests: requests,
	}

	_, err := srv.Spreadsheets.BatchUpdate(spreadsheetId, batchUpdateRequest).Do()
	if err != nil {
		return constant.ErrCommonSystemUnknownErr.NewMessage(err.Error())
	}
	return nil
}

func clearSheet(srv *sheets.Service, spreadsheetId, sheetName string) *wfmerror.WFMError {
	// 清空整个工作表的范围
	rangeToClear := fmt.Sprintf("%s!A:Z", sheetName) // 假设工作表的范围是 A 到 Z 列

	// 创建清空请求
	clearValuesRequest := &sheets.ClearValuesRequest{}
	_, err := srv.Spreadsheets.Values.Clear(spreadsheetId, rangeToClear, clearValuesRequest).Do()
	if err != nil {
		return constant.ErrCommonSystemUnknownErr.NewMessage(err.Error())
	}
	return nil
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/973047.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

架构学习第七周--Prometheus

目录 一、监控系统基础 二、Prometheus介绍 三、Prometheus单机部署 四、服务发现与告警功能 4.1,服务发现 4.2,告警功能实现 五、Prometheus与Kubernetes 5.1,Kubernetes指标 5.2,Prometheus集群部署 一、监控系统基础…

技术总结 | MySQL面试知识点

MySQL面试知识点 1.存储引擎1.1 Archive1.2 BlackHole1.3 MyISAM1.4 InnoDB (重点记一下哦)1.5 Memory1.6 CSV 2. 事务2.1. 什么是事务2.2. 事务的特性2.3. 事务的操作sql2.4. 事务的隔离级别 3.三大日志3.1. undo log 回滚日志3.2. redo log 重做日志3.3. bin log 二进制日志4…

DeepSeek模型快速部署教程-搭建自己的DeepSeek

前言:在人工智能技术飞速发展的今天,深度学习模型已成为推动各行各业智能化转型的核心驱动力。DeepSeek 作为一款领先的 AI 模型,凭借其高效的性能和灵活的部署方式,受到了广泛关注。无论是自然语言处理、图像识别,还是…

图论 之 BFS

文章目录 3243.新增道路查询后的最短距离1311.获取你好友已观看的视频 BFS:广度优先搜索(BFS) 是一种常用的算法,通常用于解决图或树的遍历问题,尤其是寻找最短路径或层级遍历的场景。BFS 的核心思想是使用队列(FIFO 数…

VSCode集成deepseek使用介绍(Visual Studio Code)

VSCode集成deepseek使用介绍(Visual Studio Code) 1. 简介 随着AI辅助编程工具的快速发展,VSCode作为一款轻量级、高度可扩展的代码编辑器,已成为开发者首选的工具之一。DeepSeek作为AI模型,结合Roo Code插件&#x…

Qt中利用httplib调用https接口

httplib中如果要调用https接口,需要开启OPENSSL支持,经过半天坑爹得摸索,总结下经验。 1,下载 并安装Win64OpenSSL 地址如下,我Qt版本是5.15.2 ,openssl选择的是 64位(Win64OpenSSL-3_3_3.msi…

使用Geotools读取DEM地形数据实战-以湖南省30米数据为例

目录 前言 一、DEM地形数据介绍 1、DEM数据简介 2、DEM应用领域 3、QGIS中读取DEM数据 二、GeoTools解析地形 1、Maven中依赖引用 2、获取数据基本信息 三、总结 前言 随着全球数字化进程的加速,各类地理空间数据呈爆炸式增长,DEM 数据作为其中的…

登录-01.基础登录功能

一.需求分析 当前的页面不需要登录就可以进入,十分不安全,因此要设置登录功能来维护系统的安全性。登录时要根据输入的用户名和密码进行登录校验,如果在数据库中没有找到匹配的用户名和密码的话,那么就无法登录。 因此要先根据用…

调用click.getchar()时Windows PyCharm无法模拟键盘输入

文章目录 问题描述解决方案参考文献 问题描述 调用 click.getchar() 时,Windows PyCharm 无法模拟键盘输入 解决方案 Run → Edit Configurations… → Modify options → Emulate terminal in output console 参考文献 Terminal emulator | PyCharm Documentati…

京东杀入外卖界,这波操作到底香不香?

京东杀入外卖界,这波操作到底香不香? 最近外卖圈炸了!京东这个电商巨头,居然一声不吭地搞起了外卖!一出手就是0佣金,品质堂食 两大杀招,直接把美团、饿了么整懵了。今天咱们就来唠唠&#xff0…

PTH 哈希传递攻击

参考文章:内网渗透 | 哈希传递攻击(Pass-the-Hash,PtH)-腾讯云开发者社区-腾讯云 哈希传递攻击(Pass-the-Hash,PtH)_c 实现 pass the hash功能-CSDN博客 域控机器账户:WIN-0V0GAORDC17 域控 ip:192.168.72.163 域内攻击者机器 ip&#xf…

Vue3项目,蛋糕商城系统

简单的vue3商城 蛋糕商城系统 下单平台 带用户 登录 注册 首页轮播图 购物车后台管理 商品订单 登录注册 商品详情 纯前端无后台、无数据库 纯Vue3项目作业 vue3 setup语法糖写法 技术实现 本项目主要使用如下技术实现, - 基于vue3vite搭建的项目框架 -…

快速上手gdb/cgdb

Linux调试器-gdb使用 1.背景2.调试原理、技巧命令2.1指令2.2 本质2.3 技巧 1.背景 程序的发布方式有两种,debug模式和release模式 Linux gcc/g出来的二进制程序,默认是release模式 要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g…

LLM增强强化学习:开启智能决策的新篇章

标题期刊年份关键词Survey on Large Language Model-Enhanced Reinforcement Learning: Concept, Taxonomy, and MethodsIEEE Transactions on Neural Networks and Learning Systems2024Reinforcement learning (RL), large language models (LLM), vision-language models (V…

ECMAScript6------数组扩展

ECMAScript6------数组扩展 1.扩展运算符1.1 含义1.2 应用(1)复制数组(浅拷贝)(2)合并数组(3)与解构赋值结合(4)字符串(5)实现了Iterator接口的对象(6)Map和Set结构,Generator 函数 2.Array.from和Array.of(1)Array.from(2)Array.of 3.新增的实例方法(1)copyWithin()(2)find(回…

C++,设计模式,【工厂方法模式】

文章目录 如何用汽车生产线理解工厂方法模式?一、传统生产方式的困境二、工厂方法模式解决方案三、模式应用场景四、模式优势分析五、现实应用启示✅C++,设计模式,【目录篇】 如何用汽车生产线理解工厂方法模式? 某个早晨,某车企CEO看着会议室里堆积如面的新车订单皱起眉…

Web入侵实战分析-常见web攻击类应急处置实验2

场景说明 某天运维人员,发现运维的公司站点被黑页,首页标题被篡改,你获得的信息如下: 操作系统:windows server 2008 R2业务:公司官网网站架构:通过phpstudy运行apache mysqlphp开放端口&…

企业内部知识库:安全协作打造企业智慧运营基石

内容概要 作为企业智慧运营的核心载体,企业内部知识库通过结构化的信息聚合与动态化的知识流动,为组织提供了从数据沉淀到价值转化的系统性框架。其底层架构以权限管理为核心,依托数据加密技术构建多层级访问控制机制,确保敏感信…

第十二届先进制造技术与材料工程国际学术会议 (AMTME 2025)

重要信息 大会官网:www.amtme.org(了解会议,投稿等) 大会时间:2025年3月21-23日 大会地点:中国-广州 简介 2025年第十二届先进制造技术与材料工程 (AMTME 2025) 定于2025年3月21-23日在中国广州隆重举…

[展示]Webrtc NoiseSuppressor降噪模块嵌入式平台移植

最近在尝试把WebRtc的NoiseSuppressor模块移植到嵌入式平台,现在已经移植了,尝试了下效果,降噪效果很显著,噪声带被显著抑制了 降噪前: 降噪后: