Android免费实现excel文件(简单)转为PDF文件

文章目录

前言:
在Android中,对于excel文件无法进行直接展示,只能通过其他方式进行间接展示,免费的相对来说比较复杂,如果只是个人使用的话或者可支持付费商用使用的话,推荐使用 Aspose.Cells进行实现,如果是简单的表格可以使用 POI+itext 的形式进行实现

1、POI依赖

导入完整的POI库的依赖:

kotlin 复制代码
implementation 'org.apache.poi:poi:5.2.3'
implementation 'org.apache.poi:poi-ooxml:5.2.3'

POI库中数据过于多,所以我用的是简化版的

下载 android5xlsx 项目中两个jar包放在自己文件的libs路径下,比添加依赖

kotlin 复制代码
 implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar', '*.so'])

2、iText的依赖

kotlin 复制代码
implementation "com.itextpdf:itextpdf:5.5.13"

字体大合集

3、将excel文件转为PDF文件

3.1 判断是否为xls和xlsx文件

kotlin 复制代码
 /**
     * 根据类型后缀名简单判断是否Excel文件
     * @param file 文件
     * @return 是否Excel文件
     */
    private fun checkIfExcelFile(file: File?): Boolean {
        if (file == null) {
            return false
        }
        val name = file.name
        //"." 需要转义字符
        val list = name.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }
            .toTypedArray()
        //划分后的小于2个元素说明不可获取类型名
        if (list.size < 2) {
            return false
        }
        val typeName = list[list.size - 1]
        //满足xls或者xlsx才可以
        return "xls" == typeName || "xlsx" == typeName

    }

3.2 将excel文件转为pdf文件

将excel文件中的单元格中字符进行循环遍历,写入到生成的pdf文件中,并对其展示效果进行处理。

kotlin 复制代码
 /**
     * 将excel文件转为Pdf文件
     * @param excelName 文件名称(带文件后缀)
     * @param path 文件存放路径
     * @param pdfName 转换后的文件名称
     */
    fun convertExcelToPdf(context: Context, excelName: String, path: String, pdfName: String) {

        if (!checkIfExcelFile(File("$path/$excelName"))) return

        var document: Document? = null
        var  writer: PdfWriter? = null
        var workbook: Workbook? = null
        var fontStream: InputStream? = null
        val pdfFile = File(path, pdfName)
        try {
            // ==================== 1. 文件路径有效性校验 ====================
            val excelFile = File("$path/$excelName")


            if (!excelFile.exists()) {
                throw FileNotFoundException("Excel文件不存在: ${excelFile.absolutePath}")
            }

            // ==================== 2. 安全初始化PDF文档 ====================
            document = Document(PageSize.A4.rotate()) // 改用A4横向以适应表格
             writer = PdfWriter.getInstance(document, FileOutputStream(pdfFile))
            document.open()

            // ==================== 3. 字体加载优化 ====================
            fontStream = try {
                context.assets.open("fonts/$ttfName")
            } catch (e: Exception) {
                throw IOException("字体文件加载失败: ${e.message}")
            }

            val fontBytes = fontStream.use { it?.readBytes() }

            val chineseFont = BaseFont.createFont(
                ttfName, // 必须包含文件后缀
                BaseFont.IDENTITY_H,
                BaseFont.EMBEDDED,
                true,
                fontBytes,
                null
            )

            // ==================== 4. 表格样式优化 ====================
            workbook = WorkbookFactory.create(excelFile)
            val sheet = workbook.getSheetAt(0)

            // 添加标题(带错误处理)
            val titleFont = Font(chineseFont, 14f, Font.BOLD)
            val title = Paragraph(sheet.sheetName, titleFont).apply {
                alignment = Element.ALIGN_CENTER
                spacingAfter = 20f // 添加标题与表格间距
            }
            document.add(title)

            // 动态计算列宽(首行作为表头)
            val headerRow = sheet.getRow(0)
            val columnWidths = FloatArray(headerRow.lastCellNum.toInt()) { 1f }
            val table = PdfPTable(columnWidths).apply {
                headerRows = 1
                widthPercentage = 100f
                setWidths(columnWidths)
            }

            // ==================== 5. 数据填充优化 ====================
            for (row in sheet) {
                for (cell in row) {
                    val cellContent = getCellValue(cell)
                    val cellFont = if (cell.rowIndex == 0) {
                        Font(chineseFont, 12f, Font.BOLD, BaseColor.WHITE)
                    } else {
                        Font(chineseFont, 10f)
                    }

                    PdfPCell(Phrase(cellContent, cellFont)).apply {
                        borderWidth = 0.1f
                        borderColor = BaseColor.DARK_GRAY
                        paddingRight = 15f
                        paddingTop = 15f
                        paddingLeft = 15f
                        paddingBottom = 15f
                        horizontalAlignment = Element.ALIGN_CENTER
                        verticalAlignment = Element.ALIGN_MIDDLE
                        if (cell.rowIndex == 0) {
                            backgroundColor = BaseColor(79, 129, 189) // 专业蓝色表头
                        }
                    }.also { table.addCell(it) }
                }
            }

            // ==================== 6. 强制刷新缓冲区 ====================
            document.add(table)
            document.close()
            document = null // 防止重复关闭

            // 验证PDF文件生成结果
            if (!pdfFile.exists() || pdfFile.length() == 0L) {
                throw IOException("PDF文件生成失败")
            }
        } catch (e: Exception) {
            // ==================== 7. 增强错误处理 ====================
            Log.e("PDF生成", "错误信息: ${e.message}", e)

            pdfFile.delete() // 删除无效文件
            throw e
        } finally {
            // ==================== 8. 安全释放资源 ====================

          val resourseList =   mutableListOf(  document to { document?.close() },
              writer to { writer?.close() },
              workbook to { workbook?.close() },
              fontStream to { fontStream?.close() })
          resourseList.forEach { (resource, closer) ->
                try {
                    closer
                } catch (e: Exception) {
                    Log.w("ResourceClose", "资源释放失败", e)
                }
            }
        }
    }

    /**
     *  辅助函数:获取单元格值(处理空单元格)
     *
     */
    private fun getCellValue(cell: Cell): String {
        Logd.t("获取单元格中的数值 ${cell}")
        return when {
            cell.cellType == Cell.CELL_TYPE_STRING -> cell.stringCellValue
            cell.cellType == Cell.CELL_TYPE_NUMERIC -> DataFormatter().formatCellValue(cell)
            else -> cell.toString()
        }
    }

尾声

上述方法只能用于简单的表格转换,对于复杂的表格转换会出现格式错乱的效果

相关推荐
nono牛21 小时前
Gatekeeper 的精确定义
android
—Miss. Z—1 天前
Power Query数据分类整合
excel
stevenzqzq1 天前
android启动初始化和注入理解3
android
城东米粉儿1 天前
compose 状态提升 笔记
android
粤M温同学1 天前
Android 实现沉浸式状态栏
android
ljt27249606611 天前
Compose笔记(六十八)--MutableStateFlow
android·笔记·android jetpack
stevenzqzq1 天前
Android Studio 断点调试核心技巧总结
android·ide·android studio
aqi001 天前
FFmpeg开发笔记(九十八)基于FFmpeg的跨平台图形用户界面LosslessCut
android·ffmpeg·kotlin·音视频·直播·流媒体
开开心心就好1 天前
系统管理工具,多功能隐私清理文件粉碎工具
java·网络·windows·r语言·电脑·excel·symfony