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
)
相关推荐
secondyoung18 小时前
Mermaid流程图高效转换为图片方案
c语言·人工智能·windows·vscode·python·docker·流程图
!chen20 小时前
Zabbix 配置中文界面、监控告警以及Windows、Linux主/被监控模板
linux·windows·zabbix
办公解码器1 天前
Excel工作表打开一次后自动销毁文件,回收站中都找不到
数据库·excel
Ya-Jun1 天前
项目实战Now in Android:项目模块说明
android·架构·kotlin
qq_316837751 天前
华为CCE k8s 使用nfs-subdir-external-provisioner 创建pvc时自动创建pv
windows·华为·kubernetes
呉師傅1 天前
国产化操作系统---银河麒麟安装步骤(简单介绍)
运维·网络·windows·单片机·电脑
百***25611 天前
MySQL 实验1:Windows 环境下 MySQL5.5 安装与配置
windows·mysql·adb
猿来是你_L1 天前
C# Dictionary 转换成 List
windows·c#·list
悟能不能悟1 天前
java List怎么转换为Vector
java·windows·list
yaoxin5211231 天前
241. Java 集合 - 使用 Collections 工厂类处理集合
java·windows