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

Swift使用xlsxreaderwriter更新Excel后无法保存问题排查

问题原因与解决方案

你碰到的这个问题其实是iOS开发里的常见坑——App的主Bundle是只读的!你直接从Bundle.main.path获取的文件路径,只能用来读取,根本没办法写入修改。哪怕控制台打印了一堆"Saving target"的日志,系统也会悄悄阻止你修改Bundle里的文件,所以你打开原文件自然看不到变化。

正确的处理流程

要解决这个问题,你需要先把Bundle里的Excel文件复制到App的Documents目录(这个目录是可读写的),之后所有的读取、修改、保存操作都针对这个副本。具体步骤如下:

  1. 编写一个工具函数,负责将Bundle里的原始文件复制到Documents目录(只需要复制一次,后续直接用Documents里的文件)
  2. 修改你的getExcelCells和saveExcelFile函数,让它们操作Documents目录里的文件路径

修改后的代码示例

首先添加复制文件的工具函数:

private func getWritableExcelPath() -> String {
    // 获取Documents目录路径
    let documentsDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    let targetPath = documentsDir.appending("/DatabaseV1.xlsx")
    
    // 如果Documents里没有这个文件,从Bundle复制过去
    let fileManager = FileManager.default
    if !fileManager.fileExists(atPath: targetPath) {
        if let sourcePath = Bundle.main.path(forResource: "DatabaseV1", ofType: "xlsx") {
            do {
                try fileManager.copyItem(atPath: sourcePath, toPath: targetPath)
            } catch {
                print("复制文件失败: \(error.localizedDescription)")
            }
        }
    }
    return targetPath
}

然后修改你的两个核心函数:

private func getExcelCells() {
    let path = getWritableExcelPath() // 用可读写的路径
    let spreadsheet: BRAOfficeDocumentPackage = BRAOfficeDocumentPackage.open(path)
    let worksheet: BRAWorksheet = spreadsheet.workbook.worksheets[0] as! BRAWorksheet
    
    var cat1 = CellModel(categoryTitle: "Best DJ", 
                        firstCell: worksheet.cell(forCellReference: "B5"), 
                        secondCell: worksheet.cell(forCellReference: "B6"), 
                        thirdCell: worksheet.cell(forCellReference: "B7"), 
                        fourthCell: worksheet.cell(forCellReference: "B8"))
    let cat2 = CellModel(categoryTitle: "Best SGA", 
                        firstCell: worksheet.cell(forCellReference: "E5"), 
                        secondCell: worksheet.cell(forCellReference: "E6"), 
                        thirdCell: worksheet.cell(forCellReference: "E7"), 
                        fourthCell: worksheet.cell(forCellReference: "E8"))
    let cat3 = CellModel(categoryTitle: "Best Greek Organization", 
                        firstCell: worksheet.cell(forCellReference: "H5"), 
                        secondCell: worksheet.cell(forCellReference: "H6"), 
                        thirdCell: worksheet.cell(forCellReference: "H7"), 
                        fourthCell: worksheet.cell(forCellReference: "H8"))
    
    excelCells += [cat1, cat2, cat3]
    cat1.cellOne.setStringValue(nominees.optionA)
    
    let data = worksheet.cell(forCellReference: "A5").stringValue()
    print(cat1.cellOne.stringValue())
    print(data)
}

private func saveExcelFile() {
    let path = getWritableExcelPath() // 用可读写的路径
    let spreadsheet: BRAOfficeDocumentPackage = BRAOfficeDocumentPackage.open(path)
    let worksheet: BRAWorksheet = spreadsheet.workbook.worksheets[0] as! BRAWorksheet
    
    worksheet.save()
    spreadsheet.save()
}

补充说明

  • 为什么控制台显示保存成功?因为xlsxreaderwriter库确实执行了内存中文件对象的保存逻辑,但它尝试写入的是Bundle里的只读路径,系统底层拒绝了这个写入操作,只是没有抛出明显的错误日志,导致你误以为保存成功。
  • 如果你想验证修改是否生效,可以在保存后,读取Documents目录里的文件内容,或者用Xcode的"Devices and Simulators"工具查看App的Documents目录里的Excel文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:10:35