You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#使用GemBoxPresentation向PPT添加图文时单文件生成问题解决

功能需求与问题说明

需要实现的目标:

  • 读取指定文件夹内的所有PNG图片
  • 每张图片单独占用一页幻灯片,图片下方标注对应文件名
  • 在第1个母版幻灯片中添加全局标题
    现有代码异常:运行后每张图片单独生成一个PPT文件,无法将所有图片汇总到同一个PPT内。

预期输出效果:所有图片汇总在同一个PPT文件内,每页幻灯片顶部显示统一的母版标题,页面居中位置展示对应图片,图片下方居中标注图片文件名。

当前存在问题的原代码如下:

//Create new powerpoint presentation
var presentation = new PresentationDocument();
//change the path format
string dir = txtPath.Text.Replace("/", "\\");
fontRootFolder = dir.Replace(Path.GetDirectoryName(dir) + Path.DirectorySeparatorChar, "");
string workingPath = Application.StartupPath + @"\Zip Extracts\" + fontRootFolder + "\\png";

if (Directory.Exists(workingPath))
{
    // Get the directory
    DirectoryInfo ImagePath = new DirectoryInfo(workingPath);
    // Using GetFiles() method to get list of all png files present in the png folder
    FileInfo[] Files = ImagePath.GetFiles();
    foreach (FileInfo fi in Files)
    {
        for (int i = 0; i < fi.Length; i++)
        {
            Cursor = Cursors.WaitCursor;
            // Get slide size.
            var size = presentation.SlideSize;

            // Set slide size.
            size.SizedFor = SlideSizeType.OnscreenShow16X10;
            size.Orientation = GemBox.Presentation.Orientation.Landscape;
            size.NumberSlidesFrom = 1;

            // Create new presentation slide.
            var slide = presentation.Slides.AddNew(SlideLayoutType.Custom);

            // Create first picture from path.
            Picture picture = null;
            using (var stream = File.OpenRead(fi.FullName))
                picture = slide.Content.AddPicture(PictureContentType.Png, stream, 1.45, 1.35, 1.45, 1.35, LengthUnit.Centimeter);

            var textBox = slide.Content.AddTextBox(ShapeGeometryType.Rectangle, 1.03, 1.03, 6, 6, LengthUnit.Centimeter);

            var paragraph = textBox.AddParagraph();
            paragraph.Format.Alignment = GemBox.Presentation.HorizontalAlignment.Center;

            paragraph.AddRun(fi.Name);

            SaveFileDialog sfd = new SaveFileDialog();
            sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            sfd.Title = "Save PowerPoint Icons";
            sfd.CheckFileExists = false;
            sfd.CheckPathExists = true;
            sfd.DefaultExt = "pptx";
            sfd.Filter = "Powerpoint Files (*.pptx) | *.pptx";
            sfd.FilterIndex = 1;
            sfd.RestoreDirectory = true;
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                presentation.Save(sfd.FileName);
                Cursor = Cursors.Default;
            }
            Cursor = Cursors.Default;
        }
    }
}
错误原因
  • 存在无效循环:for (int i = 0; i < fi.Length; i++)逻辑错误,fi.Length是当前图片文件的字节大小,不是遍历计数,会导致单张图片重复执行多次幻灯片创建逻辑
  • 逻辑位置错误:幻灯片尺寸设置、保存文件弹窗、PPT保存逻辑全部写在了文件遍历循环内部,每处理一张图片就会触发一次保存操作
  • 缺失需求逻辑:没有实现母版幻灯片添加标题的功能,同时图片和文件名文本框的位置、尺寸参数设置不合理,会出现内容重叠、偏移问题
  • 文件过滤缺失:GetFiles()会读取目标文件夹下所有类型的文件,没有过滤仅读取PNG图片
修正后可运行代码
// 初始化PPT文档,该操作仅需执行1次
var presentation = new PresentationDocument();

// 幻灯片尺寸设置仅需执行1次,放在循环外
var size = presentation.SlideSize;
size.SizedFor = SlideSizeType.OnscreenShow16X10;
size.Orientation = Orientation.Landscape;
size.NumberSlidesFrom = 1;

// 给第1个母版幻灯片添加全局标题
var masterSlide = presentation.MasterSlides[0];
var titleTextBox = masterSlide.Content.AddTextBox(ShapeGeometryType.Rectangle, 0, 0.5, 25.4, 2, LengthUnit.Centimeter);
var titlePara = titleTextBox.AddParagraph();
titlePara.Format.Alignment = HorizontalAlignment.Center;
var titleRun = titlePara.AddRun("图片批量导出PPT"); // 此处可替换为需要的母版标题文本
titleRun.Format.Bold = true;
titleRun.Format.Size = 32;

// 路径处理
string dir = txtPath.Text.Replace("/", "\\");
fontRootFolder = dir.Replace(Path.GetDirectoryName(dir) + Path.DirectorySeparatorChar, "");
string workingPath = Path.Combine(Application.StartupPath, "Zip Extracts", fontRootFolder, "png");

if (Directory.Exists(workingPath))
{
    DirectoryInfo imagePath = new DirectoryInfo(workingPath);
    // 仅过滤获取PNG格式文件
    FileInfo[] files = imagePath.GetFiles("*.png");
    
    Cursor = Cursors.WaitCursor;
    // 遍历所有图片文件
    foreach (FileInfo fi in files)
    {
        // 新建单张幻灯片
        var slide = presentation.Slides.AddNew(SlideLayoutType.Custom);
        
        // 添加图片:水平居中放置,宽18cm,高度按原图比例自动适配
        Picture picture;
        using (var stream = File.OpenRead(fi.FullName))
            picture = slide.Content.AddPicture(PictureContentType.Png, stream, 3.7, 3, 18, 0, LengthUnit.Centimeter);
        
        // 计算图片实际渲染高度,将文件名文本框放在图片正下方1cm位置
        double picBottom = picture.Position.Top + picture.Layout.Height;
        var nameTextBox = slide.Content.AddTextBox(ShapeGeometryType.Rectangle, 3.7, picBottom + 1, 18, 1.5, LengthUnit.Centimeter);
        var namePara = nameTextBox.AddParagraph();
        namePara.Format.Alignment = HorizontalAlignment.Center;
        namePara.AddRun(fi.Name);
    }

    // 所有幻灯片生成完成后,仅触发1次保存弹窗
    using (SaveFileDialog sfd = new SaveFileDialog())
    {
        sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        sfd.Title = "Save PowerPoint Icons";
        sfd.CheckFileExists = false;
        sfd.CheckPathExists = true;
        sfd.DefaultExt = "pptx";
        sfd.Filter = "Powerpoint Files (*.pptx) | *.pptx";
        sfd.FilterIndex = 1;
        sfd.RestoreDirectory = true;
        if (sfd.ShowDialog() == DialogResult.OK)
        {
            presentation.Save(sfd.FileName);
        }
    }
    Cursor = Cursors.Default;
}
修正说明
  • 所有只需执行1次的初始化、配置、保存逻辑全部移到循环外部,避免重复执行
  • 删除无效的字节长度for循环,避免重复创建幻灯片
  • 新增母版标题添加逻辑,标题会自动应用到所有幻灯片页面顶部
  • 新增PNG文件过滤,避免读取非图片文件
  • 调整图片和文件名文本框的位置,自动适配图片高度避免内容重叠,所有内容居中显示
  • 使用Path.Combine拼接路径,避免不同系统下路径分隔符兼容问题
  • 增加using语句释放SaveFileDialog资源,避免内存泄漏

内容的提问来源于stack exchange,提问作者Kamweti C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:51:29