标签 代码示例 下的文章

在日常企业办公和数据分析中,表格数据的可视化和文档化非常常见。无论是产品销售报表、库存清单,还是项目进度表,通常都会希望将数据直接导出为 Word 文档,以便打印、归档或分发。手动复制粘贴不仅效率低,而且容易出错。借助 C#,我们可以轻松将 DataTable 数据生成格式规范、可自定义样式的 Word 表格,实现自动化办公。

本文将带你完整了解从创建 Word 文档、构建表格、填充数据到保存文档的流程,并重点讲解核心技术细节和关键 API 使用方式。

文中使用的方法需要用到 Free Spire.Doc for .NET,可通过 NuGet 安装:dotnet add package FreeSpire.Doc


核心流程与实现

导出 DataTable 到 Word 文档的流程主要包括以下几个步骤:

  1. 创建 Word 文档对象及章节
  2. 添加文档标题
  3. 校验 DataTable 数据
  4. 构建 Word 表格并设置样式
  5. 填充表头与数据
  6. 保存文档

下面给出完整示例代码(已优化结构和示例数据):

using System;
using System.Data;
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
using System.Drawing;

public class DataTableToWordExporter
{
    public static void ExportDataTableToWord(DataTable dataTable, string filePath)
    {
        // 1. 创建 Word 文档
        Document document = new Document();
        Section section = document.AddSection();

        // 2. 添加文档标题
        Paragraph titlePara = section.AddParagraph();
        titlePara.Format.HorizontalAlignment = HorizontalAlignment.Center;
        TextRange titleText = titlePara.AppendText("月度产品库存报表");
        titleText.CharacterFormat.FontSize = 20;
        titleText.CharacterFormat.Bold = true;

        // 添加空行
        section.AddParagraph().AppendText(Environment.NewLine);

        // 3. 校验 DataTable 数据
        if (dataTable == null || dataTable.Rows.Count == 0)
        {
            section.AddParagraph().AppendText("当前没有可用数据。");
            document.SaveToFile(filePath, FileFormat.Docx);
            Console.WriteLine("数据为空,文档已保存。");
            return;
        }

        // 4. 创建 Word 表格
        Table table = section.AddTable(true);
        table.ResetCells(dataTable.Rows.Count + 1, dataTable.Columns.Count);

        // 设置表格整体样式
        table.TableFormat.Borders.LineWidth = 1;
        table.TableFormat.Borders.BorderType = BorderStyle.Single;
        table.TableFormat.Borders.Color = Color.Black;
        table.PreferredWidth = new PreferredWidth(WidthType.Percentage, 100);
        table.TableFormat.HorizontalAlignment = RowAlignment.Center;

        // 5. 填充表头
        TableRow headerRow = table.Rows[0];
        headerRow.IsHeader = true;
        headerRow.RowFormat.BackColor = Color.LightGray;
        headerRow.RowFormat.Height = 25;
        headerRow.RowFormat.HeightType = TableRowHeightType.Exactly;

        for (int i = 0; i < dataTable.Columns.Count; i++)
        {
            headerRow.Cells[i].CellFormat.VerticalAlignment = VerticalAlignment.Middle;
            Paragraph p = headerRow.Cells[i].AddParagraph();
            p.Format.HorizontalAlignment = HorizontalAlignment.Center;
            TextRange tr = p.AppendText(dataTable.Columns[i].ColumnName);
            tr.CharacterFormat.Bold = true;
            tr.CharacterFormat.FontSize = 11;
        }

        // 6. 填充数据行
        for (int r = 0; r < dataTable.Rows.Count; r++)
        {
            TableRow dataRow = table.Rows[r + 1];
            dataRow.RowFormat.Height = 20;
            dataRow.RowFormat.HeightType = TableRowHeightType.Exactly;

            for (int c = 0; c < dataTable.Columns.Count; c++)
            {
                dataRow.Cells[c].CellFormat.VerticalAlignment = VerticalAlignment.Middle;
                Paragraph p = dataRow.Cells[c].AddParagraph();
                p.Format.HorizontalAlignment = HorizontalAlignment.Center;
                TextRange tr = p.AppendText(dataTable.Rows[r][c].ToString());
                tr.CharacterFormat.FontSize = 10;
            }
        }

        // 7. 保存文档
        try
        {
            document.SaveToFile(filePath, FileFormat.Docx);
            Console.WriteLine($"DataTable 已成功导出到 Word 文档:{filePath}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"导出 Word 文档时发生错误:{ex.Message}");
        }
    }

    public static void Main()
    {
        // 模拟 DataTable 数据
        DataTable dt = new DataTable("Products");
        dt.Columns.Add("产品ID", typeof(int));
        dt.Columns.Add("产品名称", typeof(string));
        dt.Columns.Add("类别", typeof(string));
        dt.Columns.Add("单价", typeof(decimal));
        dt.Columns.Add("库存量", typeof(int));

        dt.Rows.Add(201, "激光打印机", "办公设备", 3200.00m, 25);
        dt.Rows.Add(202, "办公桌椅套装", "家具", 1800.00m, 15);
        dt.Rows.Add(203, "液晶显示器", "显示设备", 1500.00m, 40);
        dt.Rows.Add(204, "无线键鼠套装", "外设", 250.00m, 100);
        dt.Rows.Add(205, "移动硬盘", "存储设备", 480.00m, 60);

        string outputPath = "ProductInventoryReport.docx";
        ExportDataTableToWord(dt, outputPath);

        // 测试空数据情况
        DataTable emptyDt = new DataTable("Empty");
        emptyDt.Columns.Add("ID");
        ExportDataTableToWord(emptyDt, "EmptyReport.docx");
    }
}

以下是上面代码生成的Word文档:

C#导出DataTable到Word结果文档


核心技术解析

在这个示例中,最关键的技术点如下:

  1. Word 文档对象与章节
    Document document = new Document();
    Section section = document.AddSection();
    使用 Document 对象创建新文档,Section 提供页布局和内容容器。
  2. 表格创建与单元格操作
    Table table = section.AddTable(true);
    table.ResetCells(rows, columns);
    表格的行列数量与 DataTable 对应,单元格填充通过 AddParagraph() + AppendText() 实现。
  3. 表头样式设置
    通过 RowFormat.BackColorRowFormat.HeightTextRange.CharacterFormat 设置字体加粗、字号和单元格背景色,使表格专业美观。
  4. 数据填充与居中对齐
    利用循环遍历 DataTable.RowsDataTable.Columns,将数据逐行写入 Word 单元格,并使用 HorizontalAlignment.CenterVerticalAlignment.Middle 保持表格整齐。
  5. 空数据处理
    在 DataTable 无数据时提供提示并仍保存文档,保证程序稳健性。

核心 API 总结

类 / 属性 / 方法说明
DocumentWord 文档对象,可添加 Section、表格、段落等
Section文档章节容器,承载段落和表格
Section.AddParagraph()添加段落
Section.AddTable(bool)添加表格,参数表示是否自动适应页面宽度
Table.ResetCells(rows, cols)重置表格行列数量
TableRow表格行对象,可设置高度、背景色
TableRow.Cells单元格集合
Paragraph段落对象,可添加文本
Paragraph.AppendText(string)向段落添加文本
TextRange.CharacterFormat设置字体、字号、加粗等文本样式
CellFormat单元格格式,包括垂直对齐等
HorizontalAlignment / VerticalAlignment文本水平/垂直对齐方式
Document.SaveToFile()保存文档,支持 DOCX、PDF 等格式

总结

本文展示了如何使用 C#DataTable 数据导出为 Word 文档,实现表格化展示与自动排版。通过 Spire.Doc,你不仅可以轻松创建文档和章节,还能自动生成格式规范的表格,同时处理空数据情况,保证程序运行的稳健性。在表头样式和数据对齐的控制下,导出的文档既美观又易于阅读。掌握这些技术后,你可以将数据库或 Excel 中的业务数据快速转换为 Word 报表,大幅减少手动操作的时间,同时在企业报表自动化、数据归档和文档生成等场景中提升工作效率和专业性。

更多 Word 文档处理技巧请前往 Spire.Doc 文档中心查看。

在当今数字化的世界中,PDF(便携式文档格式)已成为文档分享和打印的标准格式。作为开发者,能够通过代码操作和打印 PDF 文档是非常实用的。本文将介绍如何使用 Spire.PDF for .NET 库打印 PDF 文档,详细说明安装步骤以及代码解析,帮助您快速上手。

Spire.PDF for .NET 简介

Spire.PDF for .NET 是一个功能丰富的 PDF 处理库,它使开发者可以在 C# 应用程序中创建、修改和打印 PDF 文件。该库不仅支持基本的 PDF 操作,还提供许多高级功能,如文本和图像提取、PDF 文件合并和安全性设置等。

主要特性

  • 创建和编辑 PDF :支持创建新的 PDF 文档和对现有文档进行编辑。
  • 打印功能 :能够打印 PDF 文档到默认或指定打印机,灵活便捷。
  • 文件转换 :能够将 PDF 文件转换为 Word、Excel 等格式,方便后续的编辑。
  • 安全性 :支持对 PDF 文件进行加密、解密和密码设置,确保文档安全。

安装 Spire.PDF for .NET

要在项目中使用 Spire.PDF,您需要先将其安装。安装的方法有以下两种:

  1. 使用 NuGet 安装

    • 打开 Visual Studio,点击“工具”->“NuGet 包管理器”->“包管理器控制台”。
    • 输入以下命令并运行:

      Install-Package Spire.PDF
  2. 使用 Visual Studio GUI

    • 在解决方案资源管理器中右键点击您的项目,选择“管理 NuGet 包”。
    • 在搜索框中输入“Spire.PDF”,找到并点击安装相关包。

这两种方法都可以将 Spire.PDF 库添加到您的项目中,便于后续使用。

打印 PDF 文档的代码示例

以下是一个简单的 C# 控制台应用程序示例,展示如何打印 PDF 文档:

using Spire.Pdf;

namespace PrintWithDefaultPrinter
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建一个 PdfDocument 对象
            PdfDocument doc = new PdfDocument();

            // 加载 PDF 文件
            doc.LoadFromFile("C:/Users/Administrator/Desktop/Input.pdf");

            // 设置打印机名称
            doc.PrintSettings.PrinterName = "Your Printer Name";

            // 设置打印页面范围
            doc.PrintSettings.SelectPageRange(1, 5); // 打印第 1 到第 5 页

            // 设置打印份数
            doc.PrintSettings.Copies = 2;

            // 设置为黑白打印
            doc.PrintSettings.Color = false;

            // 检查打印机是否支持双面打印
            if (doc.PrintSettings.CanDuplex)
            {
                doc.PrintSettings.Duplex = Duplex.Default; // 设置为默认双面打印
            }

            // 打印到默认打印机
            doc.Print();

            // 清理资源
            doc.Dispose();
        }
    }
}

代码解析

  • 创建 PdfDocument 对象 :初始化一个新的 PdfDocument 对象,用于加载和操作 PDF 文件。
  • 加载 PDF 文件 :通过 LoadFromFile 方法加载指定路径的 PDF 文件。请确保文件路径正确且文件存在。
  • 设置打印机名称 :使用 PrinterName 属性指定打印机。如果不设置,则文档会打印到默认打印机。
  • 选择打印页码范围 :通过 SelectPageRange 方法指定需要打印的页码范围,例如仅打印前五页。
  • 打印份数和颜色设置 :使用 Copies 属性设置打印份数,同时通过 Color 属性选择是否以彩色打印。设置为 false 表示以黑白打印。
  • 双面打印 :通过 CanDuplex 属性检查打印机是否支持双面打印。如果支持,则设置 Duplex 为默认双面打印选项。
  • 打印到默认打印机 :调用 Print 方法将加载的文档发送到指定的打印机。
  • 资源清理 :使用 Dispose 方法释放所有占用的资源,避免内存泄漏。

总结

使用 Spire.PDF for .NET 打印 PDF 文档是一个简单而强大的解决方案。通过本文中的示例代码和解析,您可以快速上手实现 PDF 文档的打印功能。希望这篇文章能够帮助您更好地利用 C# 进行 PDF 打印开发工作!

在现代企业和个人开发中,文档处理是不可或缺的一环。尤其是在报告演示、内容整合等场景下,PowerPoint 文件(PPT/PPTX)的自动化处理需求日益增长。当我们需要将多个演示文稿或其中的特定幻灯片合并时,手动操作不仅效率低下,而且容易出错。本文将深入探讨如何利用 Java 编程语言,结合强大的 Spire.Presentation for Java 库,实现 PowerPoiont 文件的合并,为开发者提供一套高效、灵活的解决方案。

Spire.Presentation for Java 库简介与安装

Spire.Presentation for Java 是一个功能丰富的 Java API,专为创建、读取、编辑、转换和打印 PowerPoint 演示文稿而设计。它支持 PPT、PPTX、PPS、PPSX 等多种格式,无需安装 Microsoft Office,即可在 Java 应用程序中轻松处理幻灯片、文本、图片、表格、图表、多媒体等元素。其高性能和易用性使其成为 Java 处理 PowerPoint 的理想选择。

要使用 Spire.Presentation for Java,您可以通过 Maven 配置依赖。

Maven依赖配置:

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.presentation</artifactId>
        <version>11.1.1</version>
    </dependency>
</dependencies>

您也可以直接从 Spire.Presentation for Java 官方网站下载 JAR 包,并手动添加到您的项目类路径中。

合并来自外部文件的指定幻灯片

有时我们不需要合并整个演示文稿,而仅仅需要从一个或多个文件中提取特定的幻灯片,并将其插入到目标演示文稿中。Spire.Presentation 提供了灵活的 API 来实现这一需求。

以下代码示例演示了如何从两个源 PPTX 文件中提取指定幻灯片,并将其插入到一个新的演示文稿中。

import com.spire.presentation.*;

public class MergeFiles1 {
    public static void main(String[] args) throws Exception{
        //加载文档1,获取第三张幻灯片
        Presentation ppt1 = new Presentation();
        ppt1.loadFromFile("test1.pptx");
        ISlide slide = ppt1.getSlides().get(2);

        //加载文档2,将文档1中获取的幻灯片作为第二张插入到文档2
        Presentation ppt2 = new Presentation();
        ppt2.loadFromFile("test2.pptx");
        int index = 1;
        ppt2.getSlides().insert(index,slide);

        //保存文档2
        ppt2.saveToFile("merge1.pptx",FileFormat.PPTX_2013);
        ppt2.dispose();
    }
}

代码解析:

  • new Presentation():创建一个演示文稿对象,作为我们合并操作的容器。
  • ppt1.loadFromFile():加载一个幻灯片文件作为源文档。
  • ISlide slide = ppt1.getSlides().get(2):获取源文档上的某一页幻灯片。
  • ppt2.loadFromFile():加载另一个 PowerPoint 文件作为目标文档。
  • ppt2.getSlides().insert(index,slide):将源文档获取到幻灯片插入到目标文档中,index 就是插入的位置。
  • ppt2.saveToFile():将合并后的演示文稿保存为新的 PPTX 文件。

将多个 PowerPoint 文件合并为一个新的文件

将多个完整的 PowerPoint 文件按顺序合并成一个全新的演示文稿也是一个常见的需求,尤其是在演示文稿都是关于同一主题时。Spire.Presentation 同样提供了简洁高效的方法来实现这一目标。

下面的代码示例展示了如何将两个独立的 PPTX 文件合并成一个统一的演示文稿。

import com.spire.presentation.*;

public class MergeFiles2 {
    public static void main(String[] args)throws  Exception {
        //加载文档1,文档2
        Presentation ppt1 = new Presentation();
        ppt1.loadFromFile("test1.pptx");
        Presentation ppt2 = new Presentation();
        ppt2.loadFromFile("test2.pptx");

        //遍历文档1的所有幻灯片,添加到文档2
        for(int i = 0;i<ppt1.getSlides().getCount();i++){
            ppt2.getSlides().append(ppt1.getSlides().get(i));
        }

        //保存文档2
        ppt2.saveToFile("merge2.pptx",FileFormat.PPTX_2013);
        ppt2.dispose();
    }
}

代码解析:

  • ppt2.getSlides().append(ppt1.getSlides().get():这是实现多个演示文稿合并的关键。append() 方法会将源文档中的所有幻灯片按原顺序复制到当前演示文稿的末尾。这个过程会自动处理幻灯片的主题、布局、内容等,确保合并后的演示文稿保持一致性和完整性。
  • 循环处理多个文件,确保所有源文件的幻灯片都被添加到目标演示文稿中。

结语

通过上述详细的 Java 代码示例,我们不难看出 Spire.Presentation for Java 在处理 PowerPoint 合并任务上的强大能力和便捷性。无论是精确到指定幻灯片的合并,还是将多个完整演示文稿整合,该库都能提供高效且稳定的解决方案。

这种基于 Java 的 PowerPoint 合并幻灯片编程开发技术教程极大地提升了 Java 在文档处理领域的实用性,为自动化报告生成、内容聚合等场景提供了坚实的技术支撑。掌握这些技能,开发者可以更灵活地应对各种文档处理挑战,优化工作流程,提高开发效率。未来,我们还可以进一步探索幻灯片内容的修改、格式调整乃至更复杂的自动化操作,让 Java 在 PowerPoint 技术教程 中发挥更大的作用。

精简 Excel 工作簿、删除多余或不再使用的工作表,是一种非常有效的整理方式。通过移除无关内容,可以减少冗余信息,使文件结构更加清晰,只保留最有价值的数据。删除不必要的工作表不仅有助于释放存储空间,还能让工作簿的浏览与管理更加高效、直观。

在本文中,你将学习如何使用 Spire.XLS for .NET 库,通过 C# 从 Excel 工作簿中删除指定的工作表。

安装 Spire.XLS for .NET

首先,你需要将 Spire.XLS for .NET 包中包含的 DLL 文件添加为 .NET 项目的引用。你可以通过提供的下载链接手动下载 DLL 文件并引入项目,或者直接使用 NuGet 进行安装。

PM> Install-Package Spire.XLS

在 C# 中通过索引删除工作簿中的工作表

Spire.XLS for .NET 提供了 WorksheetsCollection.RemoveAt(int index) 方法,可根据工作表在工作簿中的索引位置删除指定的工作表。

具体示例代码如下:

using Spire.Xls;
using Spire.Xls.Collections;

namespace RemoveWorksheetByIndex
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建一个 Workbook 对象
            Workbook wb = new Workbook();

            // 加载 Excel 文件
            wb.LoadFromFile(@"C:\Users\Administrator\Desktop\Input.xlsx");

            // 从工作簿中获取工作表集合
            WorksheetsCollection worksheets = wb.Worksheets;

            // 根据索引删除指定的工作表
            worksheets.RemoveAt(0);

            // 将工作簿保存为新的 Excel 文件
            wb.SaveToFile("RemoveByIndex.xlsx", ExcelVersion.Version2016);

            // 释放资源
            wb.Dispose();
        }
    }
}

在 C# 中通过工作表名称删除工作簿中的工作表

如果你已经知道需要删除的工作表名称,可以使用 WorksheetsCollection.Remove(string sheetName) 方法,直接按名称从工作簿中移除对应的工作表。

具体示例代码如下:

using Spire.Xls;
using Spire.Xls.Collections;

namespace RemoveWorksheetByName
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建一个 Workbook 对象
            Workbook wb = new Workbook();

            // 加载 Excel 文件
            wb.LoadFromFile(@"C:\Users\Administrator\Desktop\Input.xlsx");

            // 从工作簿中获取工作表集合
            WorksheetsCollection worksheets = wb.Worksheets;

            // 根据工作表名称删除指定的工作表
            worksheets.Remove("sheet2");

            // 将工作簿保存为新的 Excel 文件
            wb.SaveToFile("RemoveByName.xlsx", ExcelVersion.Version2016);

            // 释放资源
            wb.Dispose();
        }
    }
}

在 C# 中一次性删除工作簿中的所有工作表

如果需要一次性移除工作簿中的所有工作表,可以使用 WorksheetsCollection.Clear() 方法快速清空工作表集合。

具体示例代码如下:

using Spire.Xls;
using Spire.Xls.Collections;

namespace RemoveAllWorksheets
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建一个 Workbook 对象
            Workbook wb = new Workbook();

            // 加载 Excel 文件
            wb.LoadFromFile(@"C:\Users\Administrator\Desktop\Input.xlsx");

            // 从工作簿中获取工作表集合
            WorksheetsCollection worksheets = wb.Worksheets;

            // 删除所有工作表
            worksheets.Clear();

            // 将工作簿保存为新的 Excel 文件
            wb.SaveToFile("RemoveAllWorksheets.xlsx", ExcelVersion.Version2016);

            // 释放资源
            wb.Dispose();
        }
    }
}

申请临时许可证

如果你希望移除生成文档中的评估提示信息,或解除功能限制,请申请一个 为期 30 天的试用许可证。

精简 Excel 工作簿、删除多余或不再使用的工作表,是一种非常有效的整理方式。通过移除无关内容,可以减少冗余信息,使文件结构更加清晰,只保留最有价值的数据。删除不必要的工作表不仅有助于释放存储空间,还能让工作簿的浏览与管理更加高效、直观。

在本文中,你将学习如何使用 Spire.XLS for .NET 库,通过 C# 从 Excel 工作簿中删除指定的工作表。

安装 Spire.XLS for .NET

首先,你需要将 Spire.XLS for .NET 包中包含的 DLL 文件添加为 .NET 项目的引用。你可以通过提供的下载链接手动下载 DLL 文件并引入项目,或者直接使用 NuGet 进行安装。

PM> Install-Package Spire.XLS

在 C# 中通过索引删除工作簿中的工作表

Spire.XLS for .NET 提供了 WorksheetsCollection.RemoveAt(int index) 方法,可根据工作表在工作簿中的索引位置删除指定的工作表。

具体示例代码如下:

using Spire.Xls;
using Spire.Xls.Collections;

namespace RemoveWorksheetByIndex
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建一个 Workbook 对象
            Workbook wb = new Workbook();

            // 加载 Excel 文件
            wb.LoadFromFile(@"C:\Users\Administrator\Desktop\Input.xlsx");

            // 从工作簿中获取工作表集合
            WorksheetsCollection worksheets = wb.Worksheets;

            // 根据索引删除指定的工作表
            worksheets.RemoveAt(0);

            // 将工作簿保存为新的 Excel 文件
            wb.SaveToFile("RemoveByIndex.xlsx", ExcelVersion.Version2016);

            // 释放资源
            wb.Dispose();
        }
    }
}

在 C# 中通过工作表名称删除工作簿中的工作表

如果你已经知道需要删除的工作表名称,可以使用 WorksheetsCollection.Remove(string sheetName) 方法,直接按名称从工作簿中移除对应的工作表。

具体示例代码如下:

using Spire.Xls;
using Spire.Xls.Collections;

namespace RemoveWorksheetByName
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建一个 Workbook 对象
            Workbook wb = new Workbook();

            // 加载 Excel 文件
            wb.LoadFromFile(@"C:\Users\Administrator\Desktop\Input.xlsx");

            // 从工作簿中获取工作表集合
            WorksheetsCollection worksheets = wb.Worksheets;

            // 根据工作表名称删除指定的工作表
            worksheets.Remove("sheet2");

            // 将工作簿保存为新的 Excel 文件
            wb.SaveToFile("RemoveByName.xlsx", ExcelVersion.Version2016);

            // 释放资源
            wb.Dispose();
        }
    }
}

在 C# 中一次性删除工作簿中的所有工作表

如果需要一次性移除工作簿中的所有工作表,可以使用 WorksheetsCollection.Clear() 方法快速清空工作表集合。

具体示例代码如下:

using Spire.Xls;
using Spire.Xls.Collections;

namespace RemoveAllWorksheets
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建一个 Workbook 对象
            Workbook wb = new Workbook();

            // 加载 Excel 文件
            wb.LoadFromFile(@"C:\Users\Administrator\Desktop\Input.xlsx");

            // 从工作簿中获取工作表集合
            WorksheetsCollection worksheets = wb.Worksheets;

            // 删除所有工作表
            worksheets.Clear();

            // 将工作簿保存为新的 Excel 文件
            wb.SaveToFile("RemoveAllWorksheets.xlsx", ExcelVersion.Version2016);

            // 释放资源
            wb.Dispose();
        }
    }
}

申请临时许可证

如果你希望移除生成文档中的评估提示信息,或解除功能限制,请申请一个 为期 30 天的试用许可证。

importsysfromPyQt5.QtWidgetsimport(QApplication,QMainWindow,QListWidget,QVBoxLayout,QLineEdit,QWidget,QFrame)fromPyQt5.QtCoreimportQt,QEventfromPyQt5.QtWidgetsimportQDesktopWidgetimportpyautoguiimportpyperclipimporttimedefpowertoy_active_window(text):sleep_second=0.2time.sleep(sleep_second)pyautogui.hotkey("win","alt","k")time.sleep(sleep_second)pyperclip.copy(text)pyautogui.hotkey("ctrl","v")time.sleep(sleep_second)pyautogui.hotkey("enter") classCommandPalette(QWidget):def__init__(self,parent=None):super().__init__(parent)# 1. 设置 UI 属性:无边框、置顶、背景透明self.setWindowFlags(Qt.FramelessWindowHint|Qt.Dialog)self.setAttribute(Qt.WA_TranslucentBackground) # 外层容器(用于实现圆角和边框)self.container=QFrame(self)self.container.setFixedWidth(500)self.container.setStyleSheet("""QFrame {background-color: #252526;border: 1px solid #454545;border-radius: 6px;}""") layout=QVBoxLayout(self.container) # 2. 搜索输入框self.search_bar=QLineEdit()self.search_bar.setPlaceholderText("键入命令名称以筛选...")self.search_bar.setStyleSheet("""QLineEdit {background-color: #3c3c3c;color: #cccccc;border: 1px solid #007acc;padding: 6px;font-size: 14px;selection-background-color: #264f78;}""") # 3. 命令列表self.list_widget=QListWidget()self.list_widget.setStyleSheet("""QListWidget {background-color: #252526;color: #cccccc;border: none;font-size: 13px;outline: none;}QListWidget::item { padding: 10px; border-radius: 4px; }QListWidget::item:selected { background-color: #094771; color: white; }QListWidget::item:hover { background-color: #2a2d2e; }""") layout.addWidget(self.search_bar)layout.addWidget(self.list_widget) main_layout=QVBoxLayout(self)main_layout.setContentsMargins(0,0,0,0)main_layout.addWidget(self.container,alignment=Qt.AlignCenter) # 模拟命令数据# self.commands = [# "File: New File",# "Git: Commit All",# "Python: Run Current File",# "Settings: Open Settings",# "Terminal: Toggle Terminal",# "View: Layout Grid"# ]self.commands=[["1. book","book code"],["2. anti2","anti2 code"],["4. chrounim","chro"],["5.q-dir","q-dir"],]self.refresh_list("") # 信号连接self.search_bar.textChanged.connect(self.refresh_list)self.search_bar.returnPressed.connect(self.execute_selected)self.list_widget.itemClicked.connect(self.execute_selected) # 2. 当在列表中通过方向键选中某项并按回车时,触发 itemActivatedself.list_widget.itemActivated.connect(self.execute_selected) # 安装事件过滤器以捕获按键self.installEventFilter(self) defrefresh_list(self,text):self.list_widget.clear()# 简单的包含搜索(不区分大小写)# filtered = [cmd for cmd in self.commands if text.lower() in cmd.lower()]filtered=[info[0]forinfoinself.commandsiftext.lower()ininfo[0].lower()]self.list_widget.addItems(filtered)ifself.list_widget.count()>0:self.list_widget.setCurrentRow(0) defexecute_selected(self):item=self.list_widget.currentItem()ifitem:print(f"触发动作:{item.text()}")text=item.text()item=[eforeinself.commandsife[0]==text][0]send_text=item[1]print("#执行命令#:{}".format(send_text))powertoy_active_window(send_text)# self.hide()QApplication.instance().quit() defshow_palette(self):width=500height=400# 假设高度为 400self.setFixedSize(width,height) # 2. 获取屏幕中心# availableGeometry() 会避开任务栏,确保真正的视觉垂直居中screen_geo=QDesktopWidget().availableGeometry()screen_center=screen_geo.center() # 3. 计算面板位置,使其中心点与屏幕中心点重合# 我们可以通过 moveCenter 方便地实现qr=self.frameGeometry()qr.moveCenter(screen_center)self.move(qr.topLeft()) # 4. 显示并聚焦self.show()self.raise_()self.activateWindow()self.search_bar.setFocus()self.search_bar.selectAll()# 方便用户直接覆盖键入 defeventFilter(self,obj,event):ifevent.type()==QEvent.KeyPress:# Esc 键退出ifevent.key()==Qt.Key_Escape:self.hide()returnTrue# 下方向键快速进入列表选择ifevent.key()==Qt.Key_Downandself.search_bar.hasFocus():self.list_widget.setFocus()returnTruereturnsuper().eventFilter(obj,event) classMainWindow(QMainWindow):def__init__(self):super().__init__()self.setWindowTitle("PyQt5 VS Code Command Palette")self.resize(1000,700)# self.minimumSize()self.showMinimized()self.setStyleSheet("background-color: #1e1e1e;")# 模拟 VS Code 背景 # 初始化命令面板self.palette=CommandPalette(self)# self.palette.hide()self.palette.show_palette()defcenter_on_screen(self):# 获取窗口几何结构frame_geometry=self.frameGeometry() # 获取屏幕中心点# QDesktopWidget().availableGeometry() 会排除任务栏占据的空间screen_center=QDesktopWidget().availableGeometry().center() # 将窗口几何结构的中心点移动到屏幕中心点frame_geometry.moveCenter(screen_center) # 移动窗口左上角到计算出的位置self.move(frame_geometry.topLeft()) defkeyPressEvent(self,event):# 绑定快捷键 Ctrl+Shift+P (Qt.ControlModifier | Qt.ShiftModifier)if(event.modifiers()==(Qt.ControlModifier|Qt.ShiftModifier)andevent.key()==Qt.Key_P):self.palette.show_palette() if__name__=="__main__":app=QApplication(sys.argv)# 设置应用字体app.setStyle("Fusion")window=MainWindow()window.show()sys.exit(app.exec_())

这个东西的主要作用是当我输入 1 时,它会找到 ["1. book", "book code"]这一项,然后 取出book code,然后激活 window 窗口切换器
,我的窗口切换器的的快捷是Win+alt+k,本来想用 ahk 来写的,但是 ahk 写 command picker 实在是不会.

https://huodong.10155.com/h5/hdact5/basketballGame/#/

签到三天,第三天每次刷新增加一次投篮机会,理论上可以刷无限次投篮次数,bug有一定的时效性,有可能过几天就修复了,注意:只有签到满三天,在第三天的时候这个bug才会触发,第四天会重置,就不会触发这个逻辑漏洞

// 全局变量:记录执行次数和所有返回结果
let executeCount = 0; // 执行次数计数器
const requestResults = []; // 存储每次请求的返回结果

// 封装请求头配置,减少重复代码
function setCommonHeaders(xhr) {

  xhr.setRequestHeader('Accept', 'application/json, text/plain, */*');
  xhr.setRequestHeader('Content-Type', 'application/json');
  xhr.setRequestHeader('Pragma', 'no-cache');
  xhr.setRequestHeader('Cache-Control', 'no-cache');
  xhr.setRequestHeader('accessToken', 'Bearer eb2cdded-2105-4833-86c6-6b27856c8dea');
  xhr.setRequestHeader('Accept-Language', 'zh-CN,zh;q=0.9');

}

// 第一个请求:开始挑战
function startChallenge() {
  // 每次执行计数器+1
  executeCount++;
  const currentExecId = executeCount; // 记录本次执行的序号
  console.log(`===== 第 ${currentExecId} 次执行 =====`);

  const requestData = JSON.stringify({
    "activityId": 1312,
    "mobile": "你的手机号"
  });

  const xhr = new XMLHttpRequest();
  xhr.withCredentials = true;

  // 初始化本次执行的结果记录
  const currentResult = {
    execId: currentExecId, // 执行序号
    time: new Date().toLocaleString(), // 执行时间
    firstRequest: null, // 第一个请求结果
    secondRequest: null // 第二个请求结果
  };

  xhr.addEventListener('readystatechange', function () {
    if (this.readyState === this.DONE) {
      // 处理第一个请求完成后的逻辑
      if (this.status >= 200 && this.status < 300) {
        try {
          const responseData = JSON.parse(this.responseText);
          console.log(`第 ${currentExecId} 次 - 第一个请求返回结果:`, responseData);
          currentResult.firstRequest = responseData; // 记录第一个请求结果

          // 确保获取到result后再执行第二个请求
          if (responseData.result) {
            challengeResultRecord(responseData.result, currentResult);
          } else {
            const errorMsg = `第 ${currentExecId} 次 - 第一个请求未返回result字段`;
            console.error(errorMsg, responseData);
            currentResult.firstRequest = { error: errorMsg, rawData: responseData };
            // 记录本次结果
            requestResults.push(currentResult);
          }
        } catch (e) {
          const errorMsg = `第 ${currentExecId} 次 - 解析第一个请求返回数据失败`;
          console.error(errorMsg, e);
          currentResult.firstRequest = { error: errorMsg, errorDetail: e };
          // 记录本次结果
          requestResults.push(currentResult);
        }
      } else {
        const errorMsg = `第 ${currentExecId} 次 - 第一个请求失败,状态码:${this.status}`;
        console.error(errorMsg);
        currentResult.firstRequest = { error: errorMsg, statusCode: this.status };
        // 记录本次结果
        requestResults.push(currentResult);
      }
    }
  });

  xhr.open('POST', 'https://huodong.10155.com/wo_activity/basketballCheck/startChallenge');
  setCommonHeaders(xhr);
  xhr.send(requestData);
}

// 第二个请求:提交挑战结果
function challengeResultRecord(challengeId, currentResult) {
  const currentExecId = currentResult.execId;
  const requestData = JSON.stringify({
    "id": challengeId,
    "hitCount": 8
  });

  const xhr = new XMLHttpRequest();
  xhr.withCredentials = true;

  xhr.addEventListener('readystatechange', function () {
    if (this.readyState === this.DONE) {
      // 处理第二个请求完成后的逻辑
      if (this.status >= 200 && this.status < 300) {
        try {
          const responseData = JSON.parse(this.responseText);
          console.log(`第 ${currentExecId} 次 - 第二个请求返回结果:`, responseData);
          currentResult.secondRequest = responseData; // 记录第二个请求结果
        } catch (e) {
          const errorMsg = `第 ${currentExecId} 次 - 解析第二个请求返回数据失败`;
          console.error(errorMsg, e);
          currentResult.secondRequest = { error: errorMsg, errorDetail: e };
        }
      } else {
        const errorMsg = `第 ${currentExecId} 次 - 第二个请求失败,状态码:${this.status}`;
        console.error(errorMsg);
        currentResult.secondRequest = { error: errorMsg, statusCode: this.status };
      }
      // 记录本次完整结果
      requestResults.push(currentResult);
      console.log(`===== 第 ${currentExecId} 次执行完成,累计执行 ${executeCount} 次 =====`);
    }
  });

  xhr.open('POST', 'https://huodong.10155.com/wo_activity/basketballChallengeTime/challengeResultRecord');
  setCommonHeaders(xhr);
  xhr.send(requestData);
}

// 定时执行函数:每0.5秒执行一次startChallenge
function startScheduledExecution() {
  // 立即执行第一次
  startChallenge();
  
  // 之后每0.5秒执行一次(1000毫秒 = 1秒)
  setInterval(() => {
    startChallenge();
  }, 500);

  // 提供查看结果的辅助函数
  window.getExecutionResults = function() {
    console.log('===== 所有执行结果汇总 =====');
    console.log(`累计执行次数:${executeCount}`);
    console.log('执行详情:', requestResults);
    return {
      totalCount: executeCount,
      results: requestResults
    };
  };

  console.log('定时任务已启动,每0.5秒执行一次!');
  console.log('可调用 getExecutionResults() 查看所有执行记录');
}

// 启动定时执行
startScheduledExecution();

📌 转载信息
转载时间:
2026/1/3 14:40:47