kmp desktop实现excel预览

先将excel转paf

https://blog.csdn.net/qq_42761569/article/details/121699594

Kotlin 复制代码
package util

import com.aspose.cells.License
import com.aspose.cells.PdfSaveOptions
import com.aspose.cells.Workbook
import com.geolo.desktop.common.utils.LogUtils
import java.io.FileOutputStream

object ExcelUtils {
    /**
     * excel 转 pdf
     *
     * @param excelFilePath excel文件路径
     * @param convertSheets 需要转换的sheet
     */
    fun excel2pdf(excelFilePath: String, convertSheets: IntArray?) {
        excel2pdf(excelFilePath, null, convertSheets)
    }

    /**
     * excel 转 pdf
     *
     * @param excelFilePath excel文件路径
     * @param pdfFilePath   pdf文件路径
     * @param convertSheets 需要转换的sheet
     */
    /**
     * excel 转 pdf
     *
     * @param excelFilePath excel文件路径
     */
    /**
     * excel 转 pdf
     *
     * @param excelFilePath excel文件路径
     * @param pdfFilePath   pdf文件路径
     */
    @JvmOverloads
    fun excel2pdf(
        excelFilePath: String,
        pdfFilePath: String? = null,
        convertSheets: IntArray? = null
    ) {
        var pdfFilePath = pdfFilePath
        try {
            pdfFilePath = pdfFilePath ?: getPdfFilePath(excelFilePath)
            // 验证 License
            license
            val wb = Workbook(excelFilePath)
            val fileOS = FileOutputStream(pdfFilePath)
            val pdfSaveOptions = PdfSaveOptions()
            pdfSaveOptions.onePagePerSheet = true
            if (null != convertSheets) {
                printSheetPage(wb, convertSheets)
            }
            wb.save(fileOS, pdfSaveOptions)
            fileOS.flush()
            fileOS.close()
            LogUtils.d("Excel convert success")
        } catch (e: Exception) {
            LogUtils.d("Excel convert failed")
            e.printStackTrace()
        }
    }

    /**
     * 获取 生成的 pdf 文件路径,默认与源文件同一目录
     *
     * @param excelFilePath excel文件
     * @return 生成的 pdf 文件
     */
    private fun getPdfFilePath(excelFilePath: String): String {
        return excelFilePath.split(".".toRegex()).dropLastWhile { it.isEmpty() }
            .toTypedArray()[0] + ".pdf"
    }

    private val license: Unit
        /**
         * 获取 license 去除水印
         * 若不验证则转化出的pdf文档会有水印产生
         */
        get() {
            val licenseFilePath = "excel-license.xml"
            try {
                val `is` = ExcelUtils::class.java.classLoader.getResourceAsStream(licenseFilePath)
                val license = License()
                license.setLicense(`is`)
            } catch (e: Exception) {
                LogUtils.d("license verify failed")
                e.printStackTrace()
            }
        }

    /**
     * 隐藏workbook中不需要的sheet页。
     *
     * @param sheets 显示页的sheet数组
     */
    private fun printSheetPage(wb: Workbook, sheets: IntArray?) {
        for (i in 1 until wb.worksheets.count) {
            wb.worksheets[i].isVisible = false
        }
        if (null == sheets || sheets.size == 0) {
            wb.worksheets[0].isVisible = true
        } else {
            for (i in sheets.indices) {
                wb.worksheets[i].isVisible = true
            }
        }
    }
}

适用于window平台的desktop应用破的 pff预览view

https://github.com/Patr1ick/fxPDF?tab=readme-ov-file

预览控件

Kotlin 复制代码
package ui.pdfpreview

import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.awt.SwingPanel
import com.geolo.desktop.common.utils.LogUtils
import eu.patrickgeiger.fxpdf.util.PDF
import eu.patrickgeiger.fxpdf.viewer.MinimalViewer
import javafx.application.Platform
import javafx.embed.swing.JFXPanel
import javafx.scene.Scene
import javafx.scene.layout.StackPane
import java.io.File

@Composable
fun PdfPreview(
    state: PdfPreviewState,
    modifier: Modifier = Modifier,
    onCreated: (MinimalViewer) -> Unit = {},
    onDispose: (MinimalViewer) -> Unit = {},
) {
    var minimalViewer by remember { mutableStateOf<MinimalViewer?>(null) }
    val currentOnDispose by rememberUpdatedState(onDispose)

    minimalViewer?.let {
        DisposableEffect(it) {
            onDispose {
                it.pdf.closeDocument() //关闭文档
                currentOnDispose(it)
            }
        }
    }


    SwingPanel(factory = {
        JFXPanel().also { jfxP ->
            Platform.runLater {
                val rootVewView = MinimalViewer.MinimalViewerBuilder()
                    .setPDF(PDF(File(state.filePath)))
                    .build()
                minimalViewer = rootVewView
                val root = StackPane()
                root.children.add(minimalViewer)
                val scene = Scene(root)
                onCreated.invoke(rootVewView)
                jfxP.scene = scene
                Platform.enterNestedEventLoop("main") //退出后可重新进入
            }
        }

    }, modifier = modifier) {jfxpannel->
    }


}

class PdfPreviewState(
    val filePath: String
)
相关推荐
Evaporator Core33 分钟前
深入探索:Core Web Vitals 进阶优化与新兴指标
前端·windows
Mcworld8571 小时前
java集合
java·开发语言·windows
听忆.1 小时前
前端上传获取excel文件后,如何读取excel文件的内容
excel
2301_786964362 小时前
EXCEL Python 实现绘制柱状线型组合图和树状图(包含数据透视表)
python·microsoft·excel
玩电脑的辣条哥2 小时前
怎么在excel单元格1-5行中在原来内容前面加上固定一个字?
excel
hnlucky2 小时前
windows编写和调试代码工具——IDE安装
ide·windows
大强同学3 小时前
Adobe DC 2025安装教程
windows·adobe·pdf
python1564 小时前
使用Langfuse和RAGAS,搭建高可靠RAG应用
人工智能·windows·python
QQ_4376643144 小时前
单向循环链表C语言实现实现(全)
数据结构·windows·链表
CodeBlossom4 小时前
java加强 -stream流
java·windows·python