(Dalian COSCO KHI Ship Engineering CO.,LTD, Dalian 116052, China)
备注
1设计背景
-
2 程序开发
2.1设计思路镀锌管一品电子图纸文件有DXF和XDW两种类型,将两种类型的文件名分别存放到List<string> dxfFiles 和 List<string> xdwFiles 中,根据文件名到数据库检索二维码需要的信息;部分检索不到的信息,需要到DXF文件中读取;利用检索信息生成bmp格式的二维码图片,存放到临时文件夹中。图片名称与图纸文件名称相同,但文件格式不同。
DXF文件的数据格式为ASCII编码方式,无法直接插入二维码图片,因此需要先通过虚拟打印的方式将DXF文件转换成XDW文件。
利用DocuWorks开放API函数,将bmp二维码图片插入到对应的XDW文件中。插入完成后,将二维码图片删除。
将新生成的XDW文件图纸,按照编号顺序批量输出到打印机上。
2.2 关键技术及难点本程序采用微软.net framework4.5框架,开发语言为C# 6.0,开发工具为 Visual Studio 2019。此程序虽然没有复杂的业务逻辑,但依然有以下几点技术难点需要克服:
2.2.1 DXF文件插入二维码图片技术DXF文件为ASCII编码形式,而二维码图片为二进制编码形式,因此二维码图片无法直接插入到DXF文件中,需要将DXF文件先批量转换为XDW文件。此转换没有现成的解决方案,需要利用虚拟打印技术将DXF文件打印成XDW文件。为确保转换后线条颜色清晰以及字符集无乱码情况的发生,需要进行反复的程序调试。
2.2.2 DXF图纸信息数据提取技术由于ERP系统的BUG问题,该系统已过维护期,且BUG排查困难,导致部分图纸二维码信息无法在数据库表中检索到。这种情况需要从DXF图纸中检索所需要的信息加印到二维码中。解决方案是利用程序将DXF文件以文本形式打开,通过固定的图纸坐标,定位到所需要的信息,然后将其从DXF文件中读取出来,生成二维码图片。
2.2.3转换及打印进程排队技术镀锌管加工图纸一次输出近2000份,DXF和XDW两种格式混排,大约各占一半。这两种文件格式的处理程序并不完全一致,DXF文件处理更复杂、更消耗系统资源。DXF文件的转换及XDW最终的打印输出需要调用打印进程。跨进程调用需要主程序进程及打印进程的协调工作,否则会出现漏打或者顺序出错等情况的发生。解决方案是利用.net事件观察者的模式,自定义打印事件模型,确保所有打印队列按顺序进行;在转换和打印两个环节时进行事件的订阅,并将各自具体的实现方法传递给打印事件。
2.3 基本实现过程及部分源程序2.3.1 文件命名规则见图6,前4位为文件排序编号,即最终的图纸打印输出顺序。中间部分为管加工图编号,依据它可以到数据库表中检索出唯一的管子信息,用于生成二维码图片。为了确保图纸名称和二维码信息的一一对应关系不会出错,建立了两个字典Dictionary<string, string>dxfFileswithvalues 和 Dictionary<string, string>xdwFileswithvalues分别存储两种类型的文件名和二维码信息。其中文件名作为键,二维码信息作为值。
2.3.2 编写自定义函数生成二维码,DXF文件实现代码如下,XDW文件二维码生成程序处理方式相同。
createbmpfile(dxfFileswithvalues);
private void createbmpfile(Dictionary<string,string> dict)
....{
...........foreach (KeyValuePair<string, string> kv in dict)
............{
. . . . . . . . . . . QRcodehelper.Create_Qrcodebmpfile(Path.GetTempPath() + "xdw\\", kv.Key.Split(new char[] { '.' })[0] + ".bmp", 1, kv.Value);
............}}
. . . . public static string Create_Qrcodebmpfile(string Pathname,string Filename, int size, string strvalue)
....{
............if (!Directory.Exists(Pathname))
............{
. . . . . . . . . . . . . . . . DirectoryInfo di = Directory. CreateDirectory(Pathname);
............}
............Bitmap bm = Create_ImgCode(strvalue, size);//生成二维码bm
............string filename = Filename.Split(new char[] { '.' })[0] + ".bmp";
. . . . . . . . . . . . string filepath = Pathname + "\\" +filename;
............System.IO.FileStream fs = new System. IO.FileStream(filepath, System.IO.FileMode. OpenOrCreate, System.IO.FileAccess.Write);
............bm.Save(fs, System.Drawing.Imaging. ImageFormat.Bmp);
............fs.Close();
............return filepath;}
2.3.3 利用.net事件的观察者模型,将DXF文件输出到打印机DocuWorks Printer,从而实现DXF文件转换成XDW文件。部分代码如下:
private void run()
...{
. . . . . . . . . . . . p1 = new Printer("kdprnout", dxfsourcepath, dxfFiles);
............p1.Printed += new EventHandler<Printe
dEventArgs>(myprint); //订阅事件
............p1.Print();
............if (p1.m_value == p1.m_MaxValue)
..........{
..............progress(p1.m_value);
.............Thread.Sleep(3000); //确保打印结束,否则无法终止进程
................p1.Printed -= myprint; ..
................threadTimer = new System.Threading. Timer(new TimerCallback(PrintEndandCreatefile), null, 0, 500);
............}
....}
. . . . private void myprint(object send, PrintedEventArgs e)
....{
............process = new Process();
. . . . . . . . . . . . process.StartInfo.FileName =mkdprintPath;
. . . . . . . . . . . . process.StartInfo.UseShellExecute =false;
............process.StartInfo.RedirectStandardInput= true;
............process.StartInfo.
RedirectStandardOutput = true;
............process.StartInfo.RedirectStandardError= true;
............process.StartInfo.CreateNoWindow =true;
. . . . . . . . . . . . . string arguments = e.Printfile + "-device\"" + mPrinter + "\" -pA4 ";
. . . . . . . . . . . . process.StartInfo.Arguments =arguments;
............try
............{
................process.Start();
................progress(p1.m_value); .//进度条
............}
............catch (Exception ex)
............{
................MessageBox.Show(ex.ToString());
............}
............GC.Collect();
.}
2.3.4 将二维码图片插入到XDW文件中,部分代码如下:
private void mergefile()
..{
.........dxfFiles.ForEach(
............files =>
............{
..................string xdwfile = Path.GetTempPath()+ "xdw\\" + files.Split('.')[0] + ".xdw";
..................string bmpfile = Path.GetTempPath()+ "xdw\\" + files.Split('.')[0] + ".bmp";
..........XdwapiExt.XDW_add_bitmap(xdwfile, 3000, 550, bmpfile);
...............});
..}
2.3.5 将生成好的XDW文件统一输出到物理打印机上,由于此部分跟2.2.1部分实现机理相似,不同的是此处输出到物理打印机,前者输出到虚拟打印机。
上述程序代码均只是一小部分代码演示,非完整代码。
-
3 应用效果及改进展望
3.1 应用效果利用该程序可以有效避免因手工编号错误带来的无效寻找(约300H/年),每年可节约成本约7万元,大约3个月即可回收设备本体的成本,效益显著。
3.2 改进展望目前镀锌管加工图纸有DXF和XDW两种格式,插入二维码需要将DXF格式转换为XDW格式,而DXF图纸转换复杂、效率较低。目前DXF格式由TRIBON M3相关系统生成。随着新版AM12系统中船型设计作业的推广,AM12系统将逐步替换M3系统,图纸格式最终将统一为XDW文件,本程序将得以进一步优化和改进。