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

发布于:2025-04-13 ⋅ 阅读:(42) ⋅ 点赞:(0)


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

1、POI依赖

导入完整的POI库的依赖:

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

POI库中数据过于多,所以我用的是简化版的
下载 android5xlsx 项目中两个jar包放在自己文件的libs路径下,比添加依赖

 implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar', '*.so'])

在这里插入图片描述

2、iText的依赖

implementation "com.itextpdf:itextpdf:5.5.13"

字体大合集

3、将excel文件转为PDF文件

3.1 判断是否为xls和xlsx文件

 /**
     * 根据类型后缀名简单判断是否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文件中,并对其展示效果进行处理。

 /**
     * 将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()
        }
    }

尾声

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


网站公告

今日签到

点亮在社区的每一天
去签到