系列文章
【C#】最全业务单据号生成(支持定义规则、流水号、传参数)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129129787
【C#】日期范围生成器(开始日期、结束日期)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129040663
【C#】组件化开发,调用dll组件方法
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129492112
【C#】数据实体类使用
本文链接:https://blog.csdn.net/youcheng_ge/article/details/128816638
【C#】单据审批流方案
本文链接:https://blog.csdn.net/youcheng_ge/article/details/128972545
【C#】条码管理操作手册
本文链接:https://blog.csdn.net/youcheng_ge/article/details/126589496
【C#】IIS平台下,WebAPI发布及异常处理
本文链接:https://blog.csdn.net/youcheng_ge/article/details/126539836
【C#】代码模板生成工具
本文链接:https://blog.csdn.net/youcheng_ge/article/details/126890673
【C#】MySQL数据库导入工具(批量Excel插入)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/126427323
【C#】简单二维码制作和打印工具
本文链接:https://blog.csdn.net/youcheng_ge/article/details/126884228
【C#】最全单据打印(打印模板、条形码&二维码、字体样式、项目源码)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129415723
【C#】Windows服务(Service)安装及启停方案
本文链接:https://blog.csdn.net/youcheng_ge/article/details/124053794
【C#】穿透Session隔离,服务调用外部程序(无窗体界面解决)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/124053033
【C#】任务计划实现,使用Quartz类
本文链接:https://blog.csdn.net/youcheng_ge/article/details/123667723
【C#】源码解析正则表达式
本文链接:https://blog.csdn.net/youcheng_ge/article/details/118337074
【C#】软件版本和文件MD5记录(XML操作)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/112513871
【C#】测试网络是否连通
本文链接:https://blog.csdn.net/youcheng_ge/article/details/110137288
【C#】根据名称获取编码(Dictionary获取key方法)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129816701
【C#】数据建模,你是使用DataTable还是List?
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129792726
【C#】GridControl控件和数据集双向绑定
本文链接:https://blog.csdn.net/youcheng_ge/article/details/129423755
【C#】GridControl动态更换DataSource,数据查询异常处理
本文链接:https://blog.csdn.net/youcheng_ge/article/details/130305424
【C#】GridControl日期字段显示时分秒
本文链接:https://blog.csdn.net/youcheng_ge/article/details/130718303
【C#】GridControl增加选择列(不用二次点击)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/130763713
【C#】数据库检查工具(可跨库访问)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/97172329
【C#】代码解析--打印数据集
本文链接:https://blog.csdn.net/youcheng_ge/article/details/131431829
【C#】代码解析--截取整个方法函数
本文链接:https://blog.csdn.net/youcheng_ge/article/details/109817809
【C#】反射机制,动态加载类文件
本文链接:https://blog.csdn.net/youcheng_ge/article/details/131435110
文章目录
- 系列文章
- 前言
- 一、问题描述
- 二、解决方案
-
- [2.1 问题1.0版本](#2.1 问题1.0版本)
- [2.2 问题2.0版本](#2.2 问题2.0版本)
- [2.3 问题解决步骤](#2.3 问题解决步骤)
- 三、软件开发(源码)
-
- [3.1 代码](#3.1 代码)
- [3.2 结果](#3.2 结果)
- 四、项目展示
- 五、资源链接
前言
我能抽象出整个世界,但是我不能抽象你。 想让你成为私有常量,这样外部函数就无法访问你。 又想让你成为全局常量,这样在我的整个生命周期都可以调用你。 可惜世上没有这样的常量,我也无法定义你,因为你在我心中是那么的具体。
哈喽大家好,本专栏为【项目实战】,有别于【底层库】专栏,我们可以发现增加 了『问题描述』、『项目展示』章节,十分贴合项目开发流程,让读者更加清楚本文能够解决的问题、以及产品能够达到的效果。本专栏收纳项目开发过程中的解决方案,是我项目开发相对成熟、可靠方法的总结,在不涉及职务作品、保密协议 的前提下,我将问题的解决方案重新梳理,撰写本文分享给大家,大家遇到类似问题,可按本文方案处理。
本专栏会持续更新,不断完善,专栏文章关联性较弱(文章之间依赖性较弱,没有阅读顺序)。大家有任何问题,可以私信我。如果您对本专栏感兴趣,欢迎关注吧,我将带你用最简洁的代码,实现复杂的功能。
·提示:本专栏为项目实战篇,未接触项目开发的同学可能理解困难,不推荐阅读。

一、问题描述
本文主要解决MES消耗类数量逻辑处理,比如:物料消耗、打包装箱、生产订单派工等。好几个产出单子的数量合计,去完成订单数。
这个问题用纯文字很难描述,以下会引入一个小小的需求,说明一下。
二、解决方案
本文的解决方案,不会直接拿项目进行讲解,而是引入一个问题原型,采用迭代的方式,逐步细化需求,从而达到解决的目的。

2.1 问题1.0版本
需求:
1、根据图片描述,我们已经有剩余箱数的列表:15, 44, 56,合计115。
2、我们需要按照每50箱一个大箱子的规则,将剩余箱数打包成大箱子,并存储在一个列表中。
3、满50箱,为一个大箱子的整箱;不足50箱,也可以包装一个大箱子,为一个大箱子的不足箱。例如:115/50=2.3,取整为2,就是2个大箱子的整箱(里面有50个箱子);115%50=15,就是1个大箱子的不足箱(里面有15个箱子)
分析:
1、计算剩余箱数的总和。
2、计算完整的大箱子(每50箱)的数量,以及不足50箱的余数。
3、将完整的大箱子(每箱50箱)添加到列表中,然后将不足50箱的余数作为一个大箱子(如果余数大于0)添加到列表。
4、注意题目要求满50箱为一个大箱子的整箱,不足50箱也可以包装一个大箱子(即不足箱)。因此,我们得到的大箱子列表应该包含2个50和1个15。
2.2 问题2.0版本
需求增补:
1、只要每满50箱打包成一个大箱子(整箱),不足50箱的仍然保留在剩余箱数中。
2、需要从剩余箱数中取出足够的箱数来组成整箱,直到剩余箱数不足以组成一个整箱。
分析:
1、先计算总剩余箱数,然后从总剩余箱数中提取整箱(50箱)放入大箱子列表。
2、但是注意:用户要求大箱子列表只包含整箱(50箱),不足的保留在剩余箱数中。
3、然而,原始数据是三个独立的剩余箱数记录,我们可能需要重新分配这三个记录的剩余箱数,使得能够组合出整箱,同时保留不足整箱的部分。
4、注意原始剩余箱数数据是一个列表,我们需要从中组合出整箱。但是组合时,可能会跨记录组合。例如,第一个记录有15箱,第二个记录有44箱,我们可以从这两个记录中组合出一个50箱的整箱,然后这两个记录剩余的箱数分别为0和9(因为15+44=59,用去50,剩余9)。然后第三个记录56箱,可以再组合出一个50箱的整箱,剩余6箱。
2.3 问题解决步骤
步骤:
1、初始化一个整箱列表(largeBoxes)为空。
2、初始化一个临时变量boxesToDeduct为0,用于记录当前累计的箱数。
3、遍历remainingBoxes列表,对于每个记录,将其剩余箱数加到boxesToDeduct上。
4、然后,只要boxesToDeduct >= 50,我们就从boxesToDeduct中减去50,并将一个整箱(50)加入largeBoxes。
5、处理完一个记录后,将这个记录的剩余箱数更新为currentBoxes(注意,此时currentBoxes可能已经减去了一些整箱,所以是当前记录处理后的剩余箱数)。但是注意,当我们处理第一个记录时,我们可能已经将第一个记录和第二个记录的一部分组合了,所以实际上我们是在处理每个记录时,将当前记录和之前记录的剩余箱数合并处理。
但是,这样处理会导致前面记录的剩余箱数被清零(因为被取走了),而最后一个记录可能会有剩余。
三、软件开发(源码)
3.1 代码
采用的最新的net版本,项目有些变化,无主函数,需要说明。
csharp
// See https://aka.ms/new-console-template for more information
//1、 初始化剩余箱数数据
List<int> remainingBoxes = new List<int> { 15, 44, 56 };
Console.WriteLine("原始剩余箱数数据:");
Console.WriteLine($"[{string.Join(", ", remainingBoxes)}]");
//2、装箱规则(50个小箱子,包装一个大箱子。类似理解为12个啤酒瓶,包装成一个箱子)
int packingCapacity = 50;
//3、计算总箱数
int totalBoxes = 0;
foreach (int boxes in remainingBoxes)
{
totalBoxes += boxes;
}
Console.WriteLine($"总箱数: {totalBoxes}");
//4、整箱、剩余箱数计算
int fullLargeBoxes = totalBoxes / packingCapacity; // 整箱数 2
int packedBoxes = fullLargeBoxes * packingCapacity; // 整箱中小箱子数量合计 100
int remainingBoxesCount = totalBoxes % packingCapacity; // 剩余零散的小箱子 15
Console.WriteLine($"可打包完整大箱子数量: {fullLargeBoxes} (共{packedBoxes}箱)");
Console.WriteLine($"剩余箱数: {remainingBoxesCount}");
// 5、生成大箱子列表
List<int> largeBoxes = new List<int>();
for (int i = 0; i < fullLargeBoxes; i++)
{
largeBoxes.Add(packingCapacity);
}
Console.WriteLine($"\n大箱子列表 (largeBoxes):");
Console.WriteLine($"[{string.Join(", ", largeBoxes)}]");
//6、定义 更新剩余箱数数据:扣除已经打包的箱数
List<int> updatedRemainingBoxes = new List<int>();
int boxesToDeduct = packedBoxes; // 需要扣除的箱数:100箱
//7、从前往后扣除箱数
for (int i = 0; i < remainingBoxes.Count && boxesToDeduct > 0; i++)
{
if (remainingBoxes[i] >= boxesToDeduct)
{
// 当前记录的箱数足够扣除
updatedRemainingBoxes.Insert(i, remainingBoxes[i] - boxesToDeduct);
boxesToDeduct = 0;
// 前面的记录保持不变(插入到列表后面)
for (int j = i + 1; j < remainingBoxes.Count; j++)
{
updatedRemainingBoxes.Insert(i, remainingBoxes[j]);
}
}
else
{
// 当前记录的箱数不足,全部扣除
boxesToDeduct -= remainingBoxes[i];
updatedRemainingBoxes.Insert(i, 0);
}
}
Console.WriteLine($"\n更新后的剩余箱数数据 (updatedRemainingBoxes):");
Console.WriteLine($"[{string.Join(", ", updatedRemainingBoxes)}]");
//8、验证总和
int updatedSum = 0;
foreach (int boxes in updatedRemainingBoxes)
{
updatedSum += boxes;
}
updatedSum += packedBoxes; // 加上打包的大箱子数量
Console.WriteLine($"更新后总箱数: {updatedSum} (应与更新前的总箱数{totalBoxes}一致)");
Console.WriteLine("Hello, World!");
3.2 结果
bash
原始剩余箱数数据:
[15, 44, 56]
总箱数: 115
可打包完整大箱子数量: 2 (共100箱)
剩余箱数: 15
大箱子列表 (largeBoxes):
[50, 50]
更新后的剩余箱数数据 (updatedRemainingBoxes):
[0, 0, 15]
更新后总箱数: 115 (应与更新前的总箱数115一致)
Hello, World!
