You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SpreadsheetGear在UWP及Xamarin.Forms中指定路径保存Excel工作簿问题

UWP 中使用 SpreadsheetGear 保存 Excel 工作簿到指定路径

UWP 存在沙箱权限限制,直接写入任意路径可能失败,需根据目标位置选择对应方案:

1. 保存到应用本地文件夹(无需额外权限)

文件会存储在应用专属的沙箱目录,无需额外配置:

// 假设已创建 SpreadsheetGear.IWorkbook 实例
IWorkbook workbook = Factory.GetWorkbook();
string localFolderPath = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
string fullFilePath = Path.Combine(localFolderPath, "SavedExcel.xlsx");

// 调用 SpreadsheetGear 的 SaveAs 方法完成保存
workbook.SaveAs(fullFilePath, FileFormat.OpenXmlWorkbook);

2. 保存到系统文档库(需配置权限)

若要保存到系统文档库,先在 Package.appxmanifest 中配置:

  • 切换到「功能」标签,勾选「文档库」
  • 切换到「声明」标签,添加「文件类型关联」,指定 .xlsx 等 Excel 格式

之后用以下代码保存:

IWorkbook workbook = Factory.GetWorkbook();
// 获取系统文档库
StorageFolder docsFolder = KnownFolders.DocumentsLibrary;
// 创建或覆盖目标文件
StorageFile targetFile = await docsFolder.CreateFileAsync("SavedExcel.xlsx", CreationCollisionOption.ReplaceExisting);

// 通过流写入内容
using (var writeStream = await targetFile.OpenStreamForWriteAsync())
{
    workbook.SaveToStream(writeStream, FileFormat.OpenXmlWorkbook);
}

3. 让用户选择保存路径(文件选择器)

如果需要用户自定义保存位置,用 UWP 自带的 FileSavePicker:

IWorkbook workbook = Factory.GetWorkbook();

var savePicker = new FileSavePicker();
savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
savePicker.FileTypeChoices.Add("Excel 工作簿", new List<string> { ".xlsx" });
savePicker.SuggestedFileName = "SavedExcel";

StorageFile selectedFile = await savePicker.PickSaveFileAsync();
if (selectedFile != null)
{
    using (var writeStream = await selectedFile.OpenStreamForWriteAsync())
    {
        workbook.SaveToStream(writeStream, FileFormat.OpenXmlWorkbook);
    }
}

Xamarin.Forms 中保存文件到指定文件夹

Xamarin.Forms 跨平台保存需适配不同平台的文件系统规则,推荐用依赖服务实现各平台的具体逻辑:

1. 定义共享接口

在共享项目中创建文件保存接口:

public interface IFileSaver
{
    Task SaveFileAsync(string fileName, Stream fileStream, string targetFolderPath = null);
}

2. 各平台实现

UWP 平台

[assembly: Dependency(typeof(UwpFileSaver))]
namespace YourApp.UWP
{
    public class UwpFileSaver : IFileSaver
    {
        public async Task SaveFileAsync(string fileName, Stream fileStream, string targetFolderPath = null)
        {
            StorageFile targetFile;
            if (string.IsNullOrEmpty(targetFolderPath))
            {
                // 默认保存到文档库
                StorageFolder docsFolder = KnownFolders.DocumentsLibrary;
                targetFile = await docsFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
            }
            else
            {
                // 保存到指定文件夹(需确保应用有权限访问)
                StorageFolder targetFolder = await StorageFolder.GetFolderFromPathAsync(targetFolderPath);
                targetFile = await targetFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
            }

            using (var writeStream = await targetFile.OpenStreamForWriteAsync())
            {
                await fileStream.CopyToAsync(writeStream);
                await writeStream.FlushAsync();
            }
        }
    }
}

Android 平台

注意 Android 10+ 需适配 Scoped Storage,或申请 MANAGE_EXTERNAL_STORAGE 权限(Android 11+):

[assembly: Dependency(typeof(AndroidFileSaver))]
namespace YourApp.Droid
{
    public class AndroidFileSaver : IFileSaver
    {
        public async Task SaveFileAsync(string fileName, Stream fileStream, string targetFolderPath = null)
        {
            string fullFilePath;
            if (string.IsNullOrEmpty(targetFolderPath))
            {
                // 默认保存到外部存储的文档目录
                var docsDir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDocuments);
                fullFilePath = Path.Combine(docsDir.AbsolutePath, fileName);
            }
            else
            {
                fullFilePath = Path.Combine(targetFolderPath, fileName);
            }

            using (var writeStream = new FileStream(fullFilePath, FileMode.Create))
            {
                await fileStream.CopyToAsync(writeStream);
                await writeStream.FlushAsync();
            }
        }
    }
}

iOS 平台

iOS 应用仅能访问自身沙箱目录,若需让用户在文件应用中查看,可通过 UIDocumentInteractionController 分享:

[assembly: Dependency(typeof(IosFileSaver))]
namespace YourApp.iOS
{
    public class IosFileSaver : IFileSaver
    {
        public async Task SaveFileAsync(string fileName, Stream fileStream, string targetFolderPath = null)
        {
            string fullFilePath;
            if (string.IsNullOrEmpty(targetFolderPath))
            {
                // 默认保存到应用文档目录
                var docsDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                fullFilePath = Path.Combine(docsDir, fileName);
            }
            else
            {
                fullFilePath = Path.Combine(targetFolderPath, fileName);
            }

            using (var writeStream = new FileStream(fullFilePath, FileMode.Create))
            {
                await fileStream.CopyToAsync(writeStream);
                await writeStream.FlushAsync();
            }

            // 弹出菜单让用户选择打开/保存方式
            var fileUrl = new NSUrl(fullFilePath, false);
            var docController = UIDocumentInteractionController.FromUrl(fileUrl);
            docController.PresentOpenInMenu(null, null, null, null);
        }
    }
}

3. 在共享项目中调用

// 示例:从 SpreadsheetGear 获取 Excel 流
IWorkbook workbook = Factory.GetWorkbook();
var excelStream = new MemoryStream();
workbook.SaveToStream(excelStream, FileFormat.OpenXmlWorkbook);
excelStream.Position = 0;

// 调用依赖服务保存文件
await DependencyService.Get<IFileSaver>().SaveFileAsync("SavedExcel.xlsx", excelStream);

内容的提问来源于stack exchange,提问作者ProgramacionFJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 23:35:19