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

如何在安卓应用中实现点击按钮将Firebase考勤数据导出到Excel表格

安卓端Firebase考勤记录导出Excel实现方案

1. 前期准备

1.1 引入Excel生成依赖

在模块级build.gradle的dependencies块中添加Apache POI依赖,用于生成Excel文件:

implementation 'org.apache.poi:poi:4.1.2'
implementation 'org.apache.poi:poi-ooxml:4.1.2'

1.2 声明存储权限

在AndroidManifest.xml中添加文件读写相关权限,适配不同安卓版本:

<!-- 安卓12及以下存储权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- 安卓13及以上权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

同时代码中需要动态申请上述权限,获取用户授权后才能执行导出操作。

2. 核心实现步骤

2.1 绑定按钮点击事件

在Activity/Fragment中给导出按钮设置点击监听,点击后先校验权限,再拉取Firebase中的考勤数据。

2.2 拉取Firebase考勤数据

以Firestore为例,拉取考勤记录的代码示例如下,如果使用Realtime Database只需要调整对应拉取逻辑即可:

// 按钮点击事件触发拉取数据
exportBtn.setOnClickListener {
    if (checkStoragePermission()) {
        // 权限已获取,拉取考勤数据
        FirebaseFirestore.getInstance()
            .collection("attendance_records") // 替换为你自己的考勤集合名
            .get()
            .addOnSuccessListener { querySnapshot ->
                val records = querySnapshot.documents.map { it.toObject(Attendance::class.java) }.filterNotNull()
                // 数据拉取成功,执行导出
                exportExcel(records)
            }
            .addOnFailureListener {
                Toast.makeText(this, "考勤数据拉取失败,请检查网络", Toast.LENGTH_SHORT).show()
            }
    } else {
        // 申请存储权限
        requestStoragePermission()
    }
}

注:Attendance为自定义考勤数据实体类,字段需要和你Firebase中存储的考勤字段保持一致。

2.3 生成Excel并保存到本地

导出Excel的方法实现示例:

private fun exportExcel(records: List<Attendance>) {
    // 1. 创建工作簿和工作表
    val workbook = XSSFWorkbook()
    val sheet = workbook.createSheet("考勤记录")
    
    // 2. 写入表头,字段可根据实际需求调整
    val headerRow = sheet.createRow(0)
    headerRow.createCell(0).setCellValue("姓名")
    headerRow.createCell(1).setCellValue("工号")
    headerRow.createCell(2).setCellValue("打卡时间")
    headerRow.createCell(3).setCellValue("打卡类型")
    headerRow.createCell(4).setCellValue("打卡地点")
    
    // 3. 遍历考勤数据写入每行
    records.forEachIndexed { index, attendance ->
        val dataRow = sheet.createRow(index + 1)
        dataRow.createCell(0).setCellValue(attendance.name)
        dataRow.createCell(1).setCellValue(attendance.staffId)
        dataRow.createCell(2).setCellValue(attendance.checkTime)
        dataRow.createCell(3).setCellValue(attendance.type)
        dataRow.createCell(4).setCellValue(attendance.location)
    }
    
    // 4. 保存文件到系统下载目录
    val fileName = "考勤导出_${System.currentTimeMillis()}.xlsx"
    val outputStream: OutputStream?
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
            put(MediaStore.MediaColumns.MIME_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
            put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
        }
        val uri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
        outputStream = uri?.let { contentResolver.openOutputStream(it) }
    } else {
        val downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
        val file = File(downloadDir, fileName)
        outputStream = FileOutputStream(file)
    }
    
    // 写入文件并关闭资源
    outputStream?.use { stream ->
        workbook.write(stream)
        Toast.makeText(this, "导出成功,文件已保存至下载目录", Toast.LENGTH_LONG).show()
    } ?: Toast.makeText(this, "文件保存失败,请检查权限设置", Toast.LENGTH_SHORT).show()
    workbook.close()
}

3. 注意事项

  • 导出操作属于IO密集型任务,数据量大时建议放到协程/子线程中执行,避免阻塞主线程出现ANR
  • 导出过程中可以加Loading弹窗提示用户等待,避免用户重复点击按钮
  • 要处理Firebase拉取数据的异常场景,比如用户没有数据访问权限、网络断开等情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 18:36:01