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()
        }
    }

尾声

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

相关推荐
阿巴斯甜11 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker11 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952712 小时前
Andorid Google 登录接入文档
android
黄林晴13 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_1 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android