zoukankan      html  css  js  c++  java
  • C# winfrom 写了一个增值税票识别助手,可识别照片、扫描件、电子票、形成电子台帐。

       首先本小工具使用C# winfrom 实现,其中主要是使用了百度智能云OCR文字识别技术,调用期官网接口,很简单,搭配NPOI Execl操作类库,

    利用Spire.pdf类库,把pdf格式发票,转换为png图片格式。自动识别图片、pdf格式发票,发票可以用高拍仪、手机拍照、扫面件等都可以识别。

      其他说明:本程序借助百度智能云API作为基础的发票识别技术

      发票识别助手共分5个功能模块,操作相对很简单,第一步点击添加发票按钮,选择要识别的发票信息。注意说明:目前图片格式支持jpgpngbmp,图片的长和宽要求最短边大于10px

    最长边小于2048px;图像编码后大小必须小于4M,建议不要超过1M;第二步点击识别发票按钮,系统开始识别发票信息,识别完成后,发票信息会自动生成;

    介绍一下关键的代码:

    一、获取百度云API token,这个是官方给的,直接拿过来用就可以了。

     1     public static class AccessToken
     2 
     3     {
     4         // 百度云中开通对应服务应用的 API Key 建议开通应用的时候多选服务
     5         private static String clientId = ConfigurationManager.AppSettings.Get("APIKey");
     6         // 百度云中开通对应服务应用的 Secret Key
     7         private static String clientSecret = ConfigurationManager.AppSettings.Get("SecretKey");
     8 
     9         public static String getAccessToken()
    10         {
    11             String authHost = "https://aip.baidubce.com/oauth/2.0/token";
    12             HttpClient client = new HttpClient();
    13             List<KeyValuePair<String, String>> paraList = new List<KeyValuePair<string, string>>();
    14             paraList.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
    15             paraList.Add(new KeyValuePair<string, string>("client_id", clientId));
    16             paraList.Add(new KeyValuePair<string, string>("client_secret", clientSecret));
    17 
    18             HttpResponseMessage response = client.PostAsync(authHost, new FormUrlEncodedContent(paraList)).Result;
    19             String result = response.Content.ReadAsStringAsync().Result;
    20             // Console.WriteLine(result);
    21 
    22             AccessTokenInfo tokenInfo = JsonConvert.DeserializeObject<AccessTokenInfo>(result);
    23 
    24             return tokenInfo.access_token;
    25         }
    26     }
    27 
    28     public class AccessTokenInfo  
    29     {
    30         public string refresh_token { get; set; }
    31         public string expires_in { get; set; }
    32         public string session_key  { get; set; }
    33         public string access_token { get; set; }
    34         public string scope { get; set; }
    35         public string session_secret { get; set; }
    36     }

    二、增值税票识别请求过程和参数传递,也是官方给的例子,自己按照需求修改一下就可以了。

     1 // 增值税发票识别
     2         public static string vatInvoice(string fileName)
     3         {
     4             string host = "https://aip.baidubce.com/rest/2.0/ocr/v1/vat_invoice?access_token=" + token;
     5             Encoding encoding = Encoding.Default;
     6             System.Net.HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
     7             request.Method = "post";
     8             request.KeepAlive = true;
     9             // 图片的base64编码
    10             string base64 = getFileBase64(fileName);
    11             String str = "image=" + UrlEncode(base64);
    12             byte[] buffer = encoding.GetBytes(str);
    13             request.ContentLength = buffer.Length;
    14             request.GetRequestStream().Write(buffer, 0, buffer.Length);
    15             HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    16             StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
    17             string result = reader.ReadToEnd();
    18             return result;
    19         }
    20 
    21         public static String getFileBase64(String fileName)
    22         {
    23             FileStream filestream = new FileStream(fileName, FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite);
    24             byte[] arr = new byte[filestream.Length];
    25             filestream.Read(arr, 0, (int)filestream.Length);
    26             string baser64 = Convert.ToBase64String(arr);
    27             filestream.Close();
    28             return baser64;
    29         }
    30 
    31         public static string UrlEncode(string str)
    32         {
    33             StringBuilder sb = new StringBuilder();
    34             byte[] byStr = System.Text.Encoding.UTF8.GetBytes(str); //默认System.Text.Encoding.Default.GetBytes(str)
    35             for (int i = 0; i < byStr.Length; i++)
    36             {
    37                 sb.Append(@"%" + Convert.ToString(byStr[i], 16));
    38             }
    39             return (sb.ToString());
    40         }

     三、这里的部分是把pdf格式的发票,自动转换为png格式,提供出百度云api需要的文件格式。

     1 private ImageList GetImage(string[] files)
     2         {
     3             ImageList list = new ImageList();
     4             for (int i = 0; i < files.Length; i++)
     5             {
     6                 list.Images.Add(files[i], Image.FromFile(files[i]));
     7                 list.ImageSize = new Size(80, 60);
     8             }
     9             return list;
    10         }
    11 
    12         private string[] GetImages()
    13         {
    14             OpenFileDialog ofd = new OpenFileDialog();
    15             ofd.Multiselect = true;//设置 选择多个文件
    16             ofd.InitialDirectory = @"C:images";//设置初始目录  TODO:改为系统默认我的文档中的图片文件夹
    17             ofd.Multiselect = true;
    18             //ofd.Filter = "JPG(*.jpg)|*.jpg|JPEG(*.jpeg)|*.jpeg|PNG(*.png)|*.png|GIF(*.gif)|*.gif|所有文件(*.*)|*.*";
    19             ofd.Title = "请选择要识别的发票的图片";
    20             ofd.Filter = "图片文件(*.jpg *.jpeg *.bmp *.png)|*.jpg;*.jpeg;*.bmp;*.png;*.pdf";
    21             if (ofd.ShowDialog() == DialogResult.OK && ofd.FileNames != null)
    22             {
    23                 string[] files = ofd.FileNames;
    24                 //pdf文件转换为png图片文件
    25                 string imageName = "";
    26                 for (int i = 0; i < files.Length; i++)
    27                 {
    28                     if (Path.GetExtension(files[i]).ToUpper().Contains(".PDF"))
    29                     {
    30                         imageName = Path.GetFileNameWithoutExtension(files[i]);
    31                         files[i] = Common.ConvertPDF2Image(files[i], imageName, 0, 1, ImageFormat.Png);
    32                         errMsg.AppendText(DateTime.Now.ToLongTimeString().ToString() + " 已将" + imageName + ".pdf自动转换为png图片格式
    ");
    33                     }
    34                 }
    35                 return files;
    36             }
    37             else
    38             {
    39                 return null;
    40             }
    41         }
    42 
    43         //格式化日期格式
    44         public string fmartDate(string date)
    45         {
    46             date = date.Replace("", "-");
    47             date = date.Replace("", "-");
    48             date = date.Replace("", "");
    49             return date;
    50         }

     四、获取api返回的数据,输出到dataGridView中。

     1 private void 识别发票ToolStripMenuItem_Click(object sender, EventArgs e)
     2         {
     3             if (this.listView1.Items.Count == 0)
     4             {
     5                 MessageBox.Show("请先选择要识别的发票!", "消息提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
     6                 return;
     7             }
     8             
     9             Common.ShowProcessing("", this, (obj) =>
    10             {
    11                 //这里采用委托的方式解决线程卡死问题
    12                 this.Invoke(new Action(delegate
    13                 {
    14                     foreach (ListViewItem item in this.listView1.Items)
    15                     {
    16                         try
    17                         {
    18                             var invoiceInfo = JsonConvert.DeserializeObject<dynamic>(vatInvoice(item.SubItems[0].Name));
    19                             var items = invoiceInfo.words_result;
    20                             if (items != null)
    21                             {
    22                                 //写入数据表格
    23                                 int index = this.dataGridView1.Rows.Add();
    24                                 this.dataGridView1.Rows[index].Cells[0].Value = items.InvoiceType;
    25                                 this.dataGridView1.Rows[index].Cells[1].Value = items.InvoiceCode;
    26                                 this.dataGridView1.Rows[index].Cells[2].Value = items.InvoiceNum;
    27                                 this.dataGridView1.Rows[index].Cells[3].Value = fmartDate((string)items.InvoiceDate);
    28                                 this.dataGridView1.Rows[index].Cells[4].Value = items.SellerName;
    29                                 this.dataGridView1.Rows[index].Cells[5].Value = items.SellerRegisterNum;
    30                                 this.dataGridView1.Rows[index].Cells[6].Value = items.SellerAddress;
    31                                 this.dataGridView1.Rows[index].Cells[7].Value = items.SellerBank;
    32                                 this.dataGridView1.Rows[index].Cells[8].Value = Common.NumberToZero((string)items.TotalAmount);
    33                                 this.dataGridView1.Rows[index].Cells[9].Value = "0";
    34                                 if (Common.IsPropertyExist(items, "CommodityTaxRate"))
    35                                 {
    36                                     if (!Common.IsNullOrEmpty(items.CommodityTaxRate[0].word))
    37                                     {
    38                                         this.dataGridView1.Rows[index].Cells[9].Value = Common.NumberToZero((string)items.CommodityTaxRate[0].word.ToString().Replace("%", ""));
    39                                     }
    40                                 }
    41                                 this.dataGridView1.Rows[index].Cells[10].Value = Common.NumberToZero((string)items.TotalTax);
    42                                 this.dataGridView1.Rows[index].Cells[11].Value = items.AmountInFiguers;
    43                                 this.dataGridView1.Rows[index].Cells[12].Value = items.InvoiceType.ToString().Contains("电子") ? "" : "";
    44                                 this.dataGridView1.Rows[index].Cells[13].Value = items.PurchaserName;
    45                                 this.dataGridView1.Rows[index].Cells[14].Value = "一般计税";
    46                                 Application.DoEvents();
    47                                 addMessage(item.SubItems[0].Text + " 识别完成!");
    48                             }
    49                             else
    50                             {
    51                                 if (invoiceInfo.error_code != null)
    52                                 {
    53                                     addMessage(item.SubItems[0].Text + " -->" + apiErrorMessage((string)invoiceInfo.error_code));
    54                                 }
    55                             }
    56                         }
    57                         catch (Exception err)
    58                         {
    59                             addMessage(item.SubItems[0].Text + err.Message + " 识别出错,已跳过!");
    60                         }
    61                     }
    62                 }));
    63                 //这里写处理耗时的代码,代码处理完成则自动关闭该窗口
    64             }, null);
    65            
    66         }

    五、导出发票明细到EXECL表格中。

      1 private void 导出发票信息ToolStripMenuItem_Click(object sender, EventArgs e)
      2         {
      3             if (this.dataGridView1.Rows.Count == 0)
      4             {
      5                 MessageBox.Show("发票列表信息为空,不能执行导出!", "消息提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
      6                 return;
      7             }
      8 
      9             string fileName = "";
     10             SaveFileDialog sfd = new SaveFileDialog();
     11             sfd.Filter = "导出发票Excel(*.xls)|*.xls";
     12             sfd.FileName = "发票明细 - " + DateTime.Now.ToString("yyyyMMddHHmmss");
     13             if (sfd.ShowDialog() == DialogResult.OK)
     14             {
     15                 Common.ShowProcessing("正在导出,请稍候...", this, (obj) =>
     16                 {
     17                     fileName = sfd.FileName;
     18                     HSSFWorkbook wb = new HSSFWorkbook();
     19                     ISheet sheet = wb.CreateSheet("sheet1");
     20                     int columnCount = dataGridView1.ColumnCount;  //列数
     21                     int rowCount = dataGridView1.Rows.Count;      //行数
     22                     for (int i = 0; i < columnCount; i++)
     23                     {
     24                         sheet.SetColumnWidth(i, 15 * 256);
     25                     }
     26                     //报表标题
     27                     IRow row = sheet.CreateRow(0);
     28                     row.HeightInPoints = 25;
     29                     ICell cell = row.CreateCell(0);
     30                     cell.SetCellValue("发票信息台账");
     31 
     32                     ICellStyle style = wb.CreateCellStyle();
     33 
     34                     style.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
     35                     style.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;
     36 
     37                     style.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
     38                     style.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
     39                     style.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
     40                     style.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
     41                     style.FillBackgroundColor = HSSFColor.Black.Index;
     42                     style.FillForegroundColor = HSSFColor.White.Index;
     43 
     44                     IFont font = wb.CreateFont();
     45                     font.FontName = "微软雅黑";
     46                     font.FontHeightInPoints = 12;
     47                     font.Boldweight = 700;
     48                     style.SetFont(font);//将新的样式赋给单元格
     49                     cell.CellStyle = style;
     50                     sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, columnCount - 1));
     51 
     52                     //表头
     53                     IRow row1 = sheet.CreateRow(1);
     54                     row1.HeightInPoints = 20;
     55 
     56                     ICellStyle styleHead = wb.CreateCellStyle();
     57                     styleHead.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
     58                     styleHead.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;
     59                     styleHead.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
     60                     styleHead.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
     61                     styleHead.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
     62                     styleHead.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
     63                     styleHead.FillBackgroundColor = HSSFColor.Black.Index;
     64                     styleHead.FillForegroundColor = HSSFColor.White.Index;
     65 
     66                     IFont font2 = wb.CreateFont();
     67                     font2.FontName = "微软雅黑";
     68                     font2.FontHeightInPoints = 10;
     69                     font2.Boldweight = 500;
     70                     styleHead.SetFont(font2);//将新的样式赋给单元格
     71 
     72                     for (int i = 0; i < columnCount; i++)
     73                     {
     74                         ICell row1cell = row1.CreateCell(i);
     75                         row1cell.SetCellValue(dataGridView1.Columns[i].HeaderText.ToString());
     76                         row1cell.CellStyle = styleHead;
     77                     }
     78 
     79                     //明细行,从第三列开始
     80                     int rowindex = 2;
     81                     ICellStyle styleBody = wb.CreateCellStyle();
     82                     styleBody.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left;
     83                     styleBody.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;
     84                     styleBody.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
     85                     styleBody.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
     86                     styleBody.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
     87                     styleBody.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
     88                     styleBody.FillBackgroundColor = HSSFColor.Black.Index;
     89                     styleBody.FillForegroundColor = HSSFColor.White.Index;
     90 
     91                     IFont font3 = wb.CreateFont();
     92                     font3.FontName = "微软雅黑";
     93                     font3.FontHeightInPoints = 9;
     94                     font3.Boldweight = 500;
     95                     styleBody.SetFont(font3);//将新的样式赋给单元格
     96                     for (int i = 0; i < rowCount; i++)
     97                     {
     98                         IRow datarow = sheet.CreateRow(rowindex);
     99                         datarow.Height = 300;
    100                         for (int j = 0; j < columnCount; j++)
    101                         {
    102                             ICell datacell_0 = datarow.CreateCell(j);
    103                             datacell_0.SetCellValue(this.dataGridView1.Rows[i].Cells[j].Value.ToString());
    104                             datacell_0.CellStyle = styleBody;
    105                         }
    106                         rowindex += 1;
    107                     }
    108                     // 转为字节数组
    109                     MemoryStream stream = new MemoryStream();
    110                     wb.Write(stream);
    111                     var buf = stream.ToArray();
    112 
    113                     //保存为Excel文件  
    114                     using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
    115                     {
    116                         fs.Write(buf, 0, buf.Length);
    117                         fs.Flush();
    118                         MessageBox.Show("导出 EXECL 成功!", "消息提示");
    119                         addMessage("导出发票信息到Execl表完成!");
    120                     }
    121                 }, null);
    122             }
    123         }

     操作说明如下:

  • 相关阅读:
    springMVC将处理的后的数据通过post方法传给页面时,可能会出现乱码问题,下面提出解决post乱码问题的方法
    div3的e题有点水呀
    鸽天的放鸽序列---牛客网
    CodeForces
    NOIP2009 压轴---最优贸易
    在加权无向图上求出一条从1号结点到N号结点的路径,使路径上第K+1大的边权尽量小
    好久没写题解了
    皇宫看守问题(带权树上独立集)
    树的最大独立集合问题
    拓扑排序+动态规划
  • 原文地址:https://www.cnblogs.com/zhuifengnianshao/p/13932099.html
Copyright © 2011-2022 走看看