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
)
相关推荐
alexhilton7 小时前
面向开发者的系统设计:像建筑师一样思考
android·kotlin·android jetpack
葡萄城技术团队19 小时前
从100秒到10秒的性能优化,你真的掌握 Excel 的使用技巧了吗?
excel
用户0920 小时前
Gradle Cache Entries 深度探索
android·java·kotlin
叽哥20 小时前
Kotlin学习第 9 课:Kotlin 实战应用:从案例到项目
android·java·kotlin
叽哥2 天前
Kotlin学习第 8 课:Kotlin 进阶特性:简化代码与提升效率
android·java·kotlin
Kapaseker2 天前
每个Kotlin开发者应该掌握的最佳实践,第一趴
kotlin
QQ3596773452 天前
ArcGIS Pro实现基于 Excel 表格批量创建标准地理数据库(GDB)——高效数据库建库解决方案
数据库·arcgis·excel
路由侠内网穿透2 天前
本地部署 GPS 跟踪系统 Traccar 并实现外部访问
运维·服务器·网络·windows·tcp/ip
研华嵌入式2 天前
如何在高通跃龙QCS6490 Arm架构上使用Windows 11 IoT企业版?
arm开发·windows·嵌入式硬件
丑小鸭是白天鹅2 天前
Kotlin协程详细笔记之切线程和挂起函数
开发语言·笔记·kotlin