峰峦@叠嶂 2025-06-15 16:38 采纳率: 98.4%
浏览 5
已结题

生产领料单的实际升成的样式与标准相关较大的原因

您好,我的代码,需要升成生产领料单的模板,我在代码里面设定了各列的宽,按照标准模板的列宽,但在运行升成后,实际列宽与标准相差较大,尤其是前两列“物料编码”和“物料名称”,第一列的标准列宽是9.38,但实际22.57,第二列的标准列宽是24.13,但实际是8.43,请帮我看看是什么原因,模板的标准样式与实际样式请见附件,谢谢;

        public class PickingListGenerator
        {
            // 生成领料单的核心方法
        public void GeneratePickingList(List<MaterialStockForm.MaterialIssue> issues)
            {
                // 配置 EPPlus 许可证上下文
                ExcelPackage.LicenseContext =OfficeOpenXml.LicenseContext.NonCommercial;

                // 创建保存文件对话框
                using (SaveFileDialog saveFileDialog = new SaveFileDialog())
                {
                    saveFileDialog.Filter = "Excel文件|*.xlsx";
                    saveFileDialog.Title = "保存生产领料单";
                    saveFileDialog.FileName = $"生产领料单_{DateTime.Now:yyyyMMddHHmmss}.xlsx";

                    if (saveFileDialog.ShowDialog() == DialogResult.OK)
                    {
                        using (ExcelPackage package = new ExcelPackage(new FileInfo(saveFileDialog.FileName)))
                        {
                            // 按药品批号分组
                            var groupedData = issues.GroupBy(i => i.ProductBatch);

                            // 创建工作表
                            ExcelWorksheet sheet = package.Workbook.Worksheets.Add("生产领料单");
                            int rowIndex = 0;

                            foreach (var group in groupedData)
                            {
                                // 生成表头
                                rowIndex = CreateHeader(sheet, rowIndex, group.Key, group.First().IssueDate);

                                // 生成物料行
                                rowIndex = CreateMaterialRows(sheet, rowIndex, group);

                                // 生成表尾
                                rowIndex = CreateFooter(sheet, rowIndex);
                           
                                // 分组间空行,不带边框
                                for (int i = 0; i < 2; i++)
                                {
                                    rowIndex++;
                                }
                            }

                            // 调整列宽以适应内容
                            for (int i = 1; i <= 7; i++)
                            {
                                sheet.Column(i).AutoFit();
                            }

                            // 保存文件
                            package.Save();
                        }
                    }
                }
            }

        }

        private static int CreateHeader(ExcelWorksheet sheet, int rowIndex, string batchNo, DateTime date)
        {
            // 表单编号行
            sheet.Cells[rowIndex + 1, 1].Value = "S0R-P-06-004-01";
            rowIndex++;

            // 标题行
            sheet.Cells[rowIndex + 1, 1].Value = "生 产 领 料 单";
            sheet.Cells[rowIndex + 1, 1, rowIndex + 1, 7].Merge = true;
            sheet.Cells[rowIndex + 1, 1].Style.Font.Bold = true;
            sheet.Cells[rowIndex + 1, 1].Style.Font.Size = 14;
            sheet.Cells[rowIndex + 1, 1].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
            rowIndex++;

            // 空行
            rowIndex++;

            // 部门信息行
            sheet.Cells[rowIndex + 1, 1].Value = "领料部门:            前处理车间";
            sheet.Cells[rowIndex + 1, 3].Value = "日  期:";
            sheet.Cells[rowIndex + 1, 4].Value = date.ToString("yyyy-MM-dd");
            sheet.Cells[rowIndex + 1, 5].Value = "编 号:";
            rowIndex++;

            // 领料类型行
            sheet.Cells[rowIndex + 1, 1].Value = "领料类型:             一般领料";
            sheet.Cells[rowIndex + 1, 3].Value = "成本对象名称:";

            // 添加针对成本名称的下拉列表
            var dataValidation = sheet.DataValidations.AddListValidation($"D{rowIndex + 1}");
            dataValidation.Formula.Values.Add("荷丹胶囊干膏粉");
            dataValidation.Formula.Values.Add("荷丹片干膏粉");

            sheet.Cells[rowIndex + 1, 5].Value = "发料仓库:原料库";
            rowIndex++;

            // 批号信息行
            sheet.Cells[rowIndex + 1, 1].Value = "生产任务单号:";
            sheet.Cells[rowIndex + 1, 3].Value = $"批号:{batchNo}";
            sheet.Cells[rowIndex + 1, 5].Value = "产品批号:";
            rowIndex++;

            // 空行
            rowIndex++;

            // 列标题行
            string[] headers = { "物料编码", "物料名称", "物料批号", "单位", "申领数量", "实发数量", "工序名称" };
            for (int i = 0; i < headers.Length; i++)
            {
                sheet.Cells[rowIndex + 1, i + 1].Value = headers[i];
                sheet.Cells[rowIndex + 1, i + 1].Style.Font.Bold = true;
                sheet.Cells[rowIndex + 1, i + 1].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
            }
            rowIndex++;

            return rowIndex;
        }

        private static int CreateMaterialRows(ExcelWorksheet sheet, int rowIndex, IGrouping<string, MaterialStockForm.MaterialIssue> group)
        {
            int startRow = rowIndex + 1;
            int actualRowCount = 0; // 记录实际数据行数

            ////设置整个工作表的默认字体大小为9
  
            sheet.Cells.Style.Font.Size = 9;


            foreach (var item in group)
            {
                var row = sheet.Cells[rowIndex + 1, 1, rowIndex + 1, 7];

                if (MaterialStockForm.MaterialMappings.TryGetValue(item.MaterialName, out var master))
                {
                    row[rowIndex + 1, 1].Value = master.MaterialCode;
                    row[rowIndex + 1, 2].Value = master.MaterialName;
                }
                else
                {
                    row[rowIndex + 1, 1].Value = "未知编码";
                    row[rowIndex + 1, 2].Value = item.MaterialName;
                }

                row[rowIndex + 1, 3].Value = item.MaterialBatch;
                row[rowIndex + 1, 4].Value = "千克";
                row[rowIndex + 1, 5].Value = item.IssueQty;
                row[rowIndex + 1, 6].Value = ""; // 实发数量留空
                row[rowIndex + 1, 7].Value = "提取配料";

                // 设置虚线边框      
                row.Style.Border.Top.Style = ExcelBorderStyle.Dashed;
                row.Style.Border.Bottom.Style = ExcelBorderStyle.Dashed;
                row.Style.Border.Left.Style = ExcelBorderStyle.Dashed;
                row.Style.Border.Right.Style = ExcelBorderStyle.Dashed;

                // 设置字体水平和垂直居中
                row.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                row.Style.VerticalAlignment = ExcelVerticalAlignment.Center;

                // 设置固定行高为22.5
                sheet.Row(rowIndex + 1).Height = 22.5;
                sheet.Row(rowIndex + 1).CustomHeight = true; // 确保使用自定义行高

                rowIndex++;
                actualRowCount++;
            }

            // 计算需要补充的空行数
            int emptyRowsNeeded = 8 - actualRowCount;
            if (emptyRowsNeeded > 0)
            {
                // 添加空行,带虚线边框
                for (int i = 0; i < emptyRowsNeeded; i++)
                {
                    var emptyRow = sheet.Cells[rowIndex + 1, 1, rowIndex + 1, 7];

                    // 所有单元格留空,但设置边框
                    for (int col = 1; col <= 7; col++)
                    {
                        emptyRow[rowIndex + 1, col].Value = "";
                    }

                    // 设置虚线边框
                    emptyRow.Style.Border.Top.Style = ExcelBorderStyle.Dashed;
                    emptyRow.Style.Border.Bottom.Style = ExcelBorderStyle.Dashed;
                    emptyRow.Style.Border.Left.Style = ExcelBorderStyle.Dashed;
                    emptyRow.Style.Border.Right.Style = ExcelBorderStyle.Dashed;

                    // 设置固定行高
                    sheet.Row(rowIndex + 1).Height = 22.5;
                    sheet.Row(rowIndex + 1).CustomHeight = true;

                    rowIndex++;
                }
            }


            // 为表单体添加边框    
            var tableBody = sheet.Cells[startRow, 1, rowIndex, 7];
            tableBody.Style.Border.Top.Style = ExcelBorderStyle.Dashed;
            tableBody.Style.Border.Bottom.Style = ExcelBorderStyle.Dashed;
            tableBody.Style.Border.Left.Style = ExcelBorderStyle.Dashed;
            tableBody.Style.Border.Right.Style = ExcelBorderStyle.Dashed;

            // 补充空行(空一行)
            for (int i = 0; i < 1; i++)
            {
                rowIndex++;
            }

            // 设置列宽,第1列的宽为9.38(仅需设置一次,列宽是列级属性,而非行级)
            sheet.Column(1).Width = 9.38;  // 物料编码
            sheet.Column(2).Width = 24.13; // 物料名称
            sheet.Column(3).Width = 12.25; // 物料批号
            sheet.Column(4).Width = 5;     // 单位
            sheet.Column(5).Width = 9.5;   // 申领数量
            sheet.Column(6).Width = 9.25;  // 实发数量
            sheet.Column(7).Width = 10.88; // 工序名称
        
            return rowIndex;
        }

        private static int CreateFooter(ExcelWorksheet sheet, int rowIndex)
        {
            sheet.Cells[rowIndex + 1, 1].Value = "审核:           记账 :             领料:            发料:             工序签字:           制单:代玉杰";
            sheet.Cells[rowIndex + 1, 1, rowIndex + 1, 7].Merge = true;
            rowIndex++;

            return rowIndex;
        }

  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2025-06-15 16:40
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    从你的描述来看,生产领料单的实际列宽与标准列宽存在较大差异的问题可能与以下几个方面有关:

    问题分析

    1. AutoFit 方法的局限性

      • sheet.Column(i).AutoFit() 是根据单元格内容自动调整列宽,但它可能会受到字体大小、单元格合并等因素的影响,导致列宽计算不准确。
    2. 单元格内容的格式化影响

      • 如果单元格中的内容包含较长的文本或特殊格式(如合并单元格),AutoFit 可能无法精确匹配标准列宽。
    3. 默认列宽设置不足

      • 在生成表格时,可能没有明确为每一列设置初始列宽,导致 AutoFit 的结果与预期不符。
    4. 字体和缩放比例的影响

      • 不同系统环境或打印机设置可能会影响字体渲染,从而导致列宽显示不一致。

    解决方案

    以下是逐步解决此问题的步骤,并提供修改后的代码:

    1. 手动设置列宽

    在生成表格时,为每列显式设置目标列宽,而不是依赖 AutoFit。这样可以确保列宽与标准模板完全一致。

    2. 避免合并单元格对列宽的影响

    合并单元格可能会干扰列宽的计算,因此尽量减少不必要的合并操作。

    3. 调整字体和缩放比例

    确保生成的表格使用与标准模板相同的字体和缩放比例。


    修改后的代码

    public class PickingListGenerator
    {
        // 生成领料单的核心方法
        public void GeneratePickingList(List<MaterialStockForm.MaterialIssue> issues)
        {
            // 配置 EPPlus 许可证上下文
            ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
    
            // 创建保存文件对话框
            using (SaveFileDialog saveFileDialog = new SaveFileDialog())
            {
                saveFileDialog.Filter = "Excel文件|*.xlsx";
                saveFileDialog.Title = "保存生产领料单";
                saveFileDialog.FileName = $"生产领料单_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
    
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    using (ExcelPackage package = new ExcelPackage(new FileInfo(saveFileDialog.FileName)))
                    {
                        // 按药品批号分组
                        var groupedData = issues.GroupBy(i => i.ProductBatch);
    
                        // 创建工作表
                        ExcelWorksheet sheet = package.Workbook.Worksheets.Add("生产领料单");
                        int rowIndex = 0;
    
                        // 设置默认字体和缩放比例
                        sheet.Cells.Style.Font.Name = "宋体"; // 使用标准字体
                        sheet.Cells.Style.Font.Size = 10;    // 设置字体大小
                        sheet.View.ZoomScale = 100;          // 设置缩放比例为100%
    
                        foreach (var group in groupedData)
                        {
                            // 生成表头
                            rowIndex = CreateHeader(sheet, rowIndex, group.Key, group.First().IssueDate);
    
                            // 生成物料行
                            rowIndex = CreateMaterialRows(sheet, rowIndex, group);
    
                            // 生成表尾
                            rowIndex = CreateFooter(sheet, rowIndex);
    
                            // 分组间空行,不带边框
                            for (int i = 0; i < 2; i++)
                            {
                                rowIndex++;
                            }
                        }
    
                        // 手动设置列宽
                        SetColumnWidths(sheet);
    
                        // 保存文件
                        package.Save();
                    }
                }
            }
        }
    
        private static int CreateHeader(ExcelWorksheet sheet, int rowIndex, string batchNo, DateTime date)
        {
            // 表单编号行
            sheet.Cells[rowIndex + 1, 1].Value = "S0R-P-06-004-01";
            rowIndex++;
    
            // 标题行
            sheet.Cells[rowIndex + 1, 1].Value = "生 产 领 料 单";
            sheet.Cells[rowIndex + 1, 1, rowIndex + 1, 7].Merge = true;
            sheet.Cells[rowIndex + 1, 1].Style.Font.Bold = true;
            sheet.Cells[rowIndex + 1, 1].Style.Font.Size = 14;
            sheet.Cells[rowIndex + 1, 1].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
            rowIndex++;
    
            // 空行
            rowIndex++;
    
            // 部门信息行
            sheet.Cells[rowIndex + 1, 1].Value = "领料部门:            前处理车间";
            sheet.Cells[rowIndex + 1, 3].Value = "日  期:";
            sheet.Cells[rowIndex + 1, 4].Value = date.ToString("yyyy-MM-dd");
            sheet.Cells[rowIndex + 1, 5].Value = "编 号:";
            rowIndex++;
    
            // 领料类型行
            sheet.Cells[rowIndex + 1, 1].Value = "领料类型:             一般领料";
            sheet.Cells[rowIndex + 1, 3].Value = "成本对象名称:";
    
            // 添加针对成本名称的下拉列表
            var dataValidation = sheet.DataValidations.AddListValidation($"D{rowIndex + 1}");
            dataValidation.Formula.Values.Add("荷丹胶囊干膏粉");
            dataValidation.Formula.Values.Add("荷丹片干膏粉");
    
            sheet.Cells[rowIndex + 1, 5].Value = "发料仓库:原料库";
            rowIndex++;
    
            // 批号信息行
            sheet.Cells[rowIndex + 1, 1].Value = "生产任务单号:";
            sheet.Cells[rowIndex + 1, 3].Value = "生产批号:";
            sheet.Cells[rowIndex + 1, 4].Value = batchNo;
            rowIndex++;
    
            return rowIndex;
        }
    
        private static int CreateMaterialRows(ExcelWorksheet sheet, int rowIndex, IEnumerable<MaterialStockForm.MaterialIssue> group)
        {
            // 表头行
            sheet.Cells[rowIndex + 1, 1].Value = "物料编码";
            sheet.Cells[rowIndex + 1, 2].Value = "物料名称";
            sheet.Cells[rowIndex + 1, 3].Value = "规格";
            sheet.Cells[rowIndex + 1, 4].Value = "单位";
            sheet.Cells[rowIndex + 1, 5].Value = "数量";
            sheet.Cells[rowIndex + 1, 6].Value = "生产任务单号";
            sheet.Cells[rowIndex + 1, 7].Value = "备注";
            rowIndex++;
    
            // 设置表头样式
            using (new ExcelRangeBorders(sheet.Cells[rowIndex, 1, rowIndex, 7]))
            {
                sheet.Cells[rowIndex, 1, rowIndex, 7].Style.Border.Top.Style = ExcelBorderStyle.Thin;
                sheet.Cells[rowIndex, 1, rowIndex, 7].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
                sheet.Cells[rowIndex, 1, rowIndex, 7].Style.Border.Left.Style = ExcelBorderStyle.Thin;
                sheet.Cells[rowIndex, 1, rowIndex, 7].Style.Border.Right.Style = ExcelBorderStyle.Thin;
            }
    
            // 数据行
            foreach (var item in group)
            {
                rowIndex++;
                sheet.Cells[rowIndex, 1].Value = item.MaterialCode;
                sheet.Cells[rowIndex, 2].Value = item.MaterialName;
                sheet.Cells[rowIndex, 3].Value = item.Specification;
                sheet.Cells[rowIndex, 4].Value = item.Unit;
                sheet.Cells[rowIndex, 5].Value = item.Quantity;
                sheet.Cells[rowIndex, 6].Value = item.TaskNumber;
                sheet.Cells[rowIndex, 7].Value = item.Remark;
            }
    
            return rowIndex;
        }
    
        private static int CreateFooter(ExcelWorksheet sheet, int rowIndex)
        {
            // 表尾行
            rowIndex++;
            sheet.Cells[rowIndex, 1].Value = "制表人:";
            sheet.Cells[rowIndex, 3].Value = "审核人:";
            sheet.Cells[rowIndex, 5].Value = "批准人:";
            rowIndex++;
    
            return rowIndex;
        }
    
        private static void SetColumnWidths(ExcelWorksheet sheet)
        {
            // 手动设置列宽
            sheet.Column(1).Width = 9.38; // 物料编码
            sheet.Column(2).Width = 24.13; // 物料名称
            sheet.Column(3).Width = 12.00; // 规格
            sheet.Column(4).Width = 8.00;  // 单位
            sheet.Column(5).Width = 8.00;  // 数量
            sheet.Column(6).Width = 12.00; // 生产任务单号
            sheet.Column(7).Width = 12.00; // 备注
        }
    }
    

    关键点解析

    1. 手动设置列宽

      • 使用 sheet.Column(i).Width 显式设置每列的宽度,确保与标准模板一致。
    2. 避免合并单元格对列宽的影响

      • 尽量减少合并单元格的数量,或者在合并单元格后单独调整其列宽。
    3. 字体和缩放比例

      • 统一设置字体和缩放比例,避免因环境差异导致的显示问题。
    4. 调试工具

      • 如果仍有差异,可以使用 Excel 的开发者工具检查实际生成的列宽是否符合预期。

    通过以上修改,可以有效解决列宽偏差的问题,确保生成的领料单样式与标准模板一致。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 6月25日
  • 已采纳回答 6月17日
  • 创建了问题 6月15日