求助:如何在C#中读写Office 365 SharePoint在线Excel文件
嘿,刚好之前做过类似的需求,给你分享两种在C#里读写Office 365 SharePoint在线Excel文件的靠谱方法,都是基于你已经拥有该文件读写权限的前提哈~
方法一:使用Microsoft Graph API(微软官方推荐)
这是目前最现代的方式,微软官方主推,支持控制台、Web、桌面等各种应用场景,不用直接操作文件流就能读写单元格数据,非常方便。
准备工作
- 先在Azure AD里注册一个应用:如果是桌面/控制台这类交互式应用,选「公共客户端」;如果是后台服务,选「机密客户端」。给应用分配Files.ReadWrite.All(针对所有文件)或者Sites.ReadWrite.All(针对站点)的权限——如果是用户上下文用委派权限,后台服务就用应用权限,记得让租户管理员授予管理员同意,不然会有权限报错。
- 安装两个必备的NuGet包:
Install-Package Microsoft.Graph Install-Package Microsoft.Identity.Client
代码示例
1. 认证获取Graph客户端
这里以后台服务的应用权限模式为例(不用用户登录):
using Microsoft.Graph; using Microsoft.Identity.Client; // 替换成你的Azure应用信息 var clientId = "你的Azure应用ID"; var tenantId = "你的Office 365租户ID"; var clientSecret = "你的应用密钥"; var confidentialClient = ConfidentialClientApplicationBuilder .Create(clientId) .WithTenantId(tenantId) .WithClientSecret(clientSecret) .Build(); var authProvider = new ClientCredentialProvider(confidentialClient); var graphClient = new GraphServiceClient(authProvider);
2. 读取Excel文件数据
直接读取指定工作表的指定范围,不用下载整个文件:
// 替换成你的文件信息:可以用文件ID,或者站点相对路径(比如"/sites/你的站点名/Shared Documents/测试.xlsx") var fileId = "你的在线Excel文件ID"; var sheetName = "Sheet1"; // 替换成你的工作表名称 // 读取已使用的区域,也可以指定具体范围比如"A1:Z50" var usedRange = await graphClient.Drives["你的Drive ID"].Items[fileId] .Workbook.Worksheets[sheetName] .UsedRange .Request() .GetAsync(); // 遍历打印数据 foreach (var row in usedRange.Values) { Console.WriteLine(string.Join(", ", row)); }
小贴士:不知道文件ID的话,可以从SharePoint文件的URL里提取(URL里的
id=参数就是),或者用Graph的搜索接口根据文件名查找。
3. 更新Excel文件数据
可以单独更新某个单元格,也可以批量更新范围:
// 示例:更新B2单元格的值 var updateRange = new WorkbookRange { Values = new object[,] { { "这是更新后的值" } } }; await graphClient.Drives["你的Drive ID"].Items[fileId] .Workbook.Worksheets[sheetName] .Range("B2") .Request() .PatchAsync(updateRange);
如果需要做复杂的Excel修改(比如插入行、设置格式),可以先把文件下载到本地修改,再上传覆盖原文件:
// 下载原文件到流 using var fileStream = new MemoryStream(); await graphClient.Drives["你的Drive ID"].Items[fileId] .Content .Request() .GetAsync() .Result.CopyToAsync(fileStream); // 这里用Open XML SDK修改流里的Excel内容(需要安装DocumentFormat.OpenXml包) // ... 你的修改逻辑 ... // 上传覆盖原文件 fileStream.Position = 0; await graphClient.Drives["你的Drive ID"].Items[fileId] .Content .Request() .PutAsync<DriveItem>(fileStream);
这是传统的SharePoint开发方式,适合已经熟悉CSOM的开发者,不需要依赖Azure AD应用,直接用SharePoint账号认证。
准备工作
- 安装CSOM的NuGet包:
Install-Package Microsoft.SharePointOnline.CSOM - 如果要解析Excel内容,还需要安装Open XML SDK:
Install-Package DocumentFormat.OpenXml
代码示例
1. 认证获取ClientContext
using Microsoft.SharePoint.Client; using System.Security; var siteUrl = "你的SharePoint站点URL,比如https://你的租户.sharepoint.com/sites/你的站点名"; var userName = "你的Office 365账号"; var password = "你的密码(如果开了MFA,得用App密码)"; // 转换为安全字符串 var securePwd = new SecureString(); foreach (char c in password) securePwd.AppendChar(c); var ctx = new ClientContext(siteUrl); ctx.Credentials = new SharePointOnlineCredentials(userName, securePwd);
踩坑提醒:如果你的账号开启了MFA,直接用用户名密码会认证失败,得在Office 365里启用App密码,用App密码代替普通密码。
2. 读取Excel文件数据
CSOM本身不直接解析Excel,需要先把文件下载到流,再用Open XML读取:
using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Spreadsheet; // 获取文件对象 var fileRelativeUrl = "/sites/你的站点名/Shared Documents/测试.xlsx"; var file = ctx.Web.GetFileByServerRelativeUrl(fileRelativeUrl); ctx.Load(file); ctx.ExecuteQuery(); // 下载文件到内存流 using var memoryStream = new MemoryStream(); file.OpenBinaryStream().CopyTo(memoryStream); memoryStream.Position = 0; // 用Open XML读取数据 using var spreadsheetDoc = SpreadsheetDocument.Open(memoryStream, false); var workbookPart = spreadsheetDoc.WorkbookPart; var worksheetPart = workbookPart.WorksheetParts.First(); var sheetData = worksheetPart.Worksheet.Elements<SheetData>().First(); foreach (var row in sheetData.Elements<Row>()) { foreach (var cell in row.Elements<Cell>()) { // 处理共享字符串类型的单元格 var cellValue = cell.InnerText; if (cell.DataType?.Value == CellValues.SharedString) { cellValue = workbookPart.SharedStringTablePart.SharedStringTable .Elements<SharedStringItem>() .ElementAt(int.Parse(cellValue)).InnerText; } Console.Write(cellValue + "\t"); } Console.WriteLine(); }
3. 更新Excel文件数据
先修改流里的Excel内容,再上传覆盖原文件:
// 重新读取文件到可写流 memoryStream.Position = 0; using var editableDoc = SpreadsheetDocument.Open(memoryStream, true); var workbookPart = editableDoc.WorkbookPart; var worksheetPart = workbookPart.WorksheetParts.First(); var sheetData = worksheetPart.Worksheet.Elements<SheetData>().First(); // 示例:修改第一行第一列的单元格值 var firstRow = sheetData.Elements<Row>().First(); var firstCell = firstRow.Elements<Cell>().First(); firstCell.CellValue = new CellValue("更新后的内容"); firstCell.DataType = new EnumValue<CellValues>(CellValues.String); // 保存修改 worksheetPart.Worksheet.Save(); memoryStream.Position = 0; // 上传覆盖原文件 file.SaveBinaryStream(memoryStream); ctx.ExecuteQuery();
两种方法各有优劣:Graph API更灵活,支持更多场景,不用处理复杂的Excel解析;CSOM更贴近传统SharePoint生态,适合已有CSOM技术栈的项目。根据你的实际需求选就行~
内容的提问来源于stack exchange,提问作者archana




