如何在安卓应用中实现点击按钮将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
相关产品推荐
相关产品推荐

