创建 操作类拓展方法:

public static class DataGridViewPro{#region 显示统计列/// <summary>/// 显示DataGridView的统计信息/// </summary>/// <param name="dgv"></param>/// <param name="SummaryColumns">要统计的列名称或数据源绑定列名称</param>public static void ShowSummary(this DataGridView dgv, string[] SummaryColumns){SummaryControlContainer summaryControl = new SummaryControlContainer(dgv, SummaryColumns);dgv.Controls.Add(summaryControl);//dgv.Tag = summaryControl;summaryControl.BringToFront();summaryControl.Show();}/// <summary>/// 显示DataGridView的统计信息/// </summary>/// <param name="dgv"></param>/// <param name="DisplaySumRowHeader">是否显示合计行标题</param>/// <param name="SumRowHeaderText">合计列标题</param>/// <param name="SumRowHeaderTextBold">合计列标题用粗体显示</param>/// <param name="SummaryColumns">要统计的列名称或数据源绑定列名称</param>public static void ShowSummary(this DataGridView dgv, bool DisplaySumRowHeader, string SumRowHeaderText, bool SumRowHeaderTextBold, string[] SummaryColumns){SummaryControlContainer summaryControl = new SummaryControlContainer(dgv, DisplaySumRowHeader, SumRowHeaderText, SumRowHeaderTextBold, SummaryColumns);dgv.Controls.Add(summaryControl);//dgv.Tag = summaryControl;summaryControl.BringToFront();summaryControl.Show();}}#endregioninternal class SummaryControlContainer : UserControl{#region 公有属性private bool _DisplaySumRowHeader;/// <summary>/// 是否显示合计行标题/// </summary>public bool DisplaySumRowHeader{get { return _DisplaySumRowHeader; }set { _DisplaySumRowHeader = value; }}private string _SumRowHeaderText = "合计";/// <summary>/// 合计列标题/// </summary>public string SumRowHeaderText{get{if (_DisplaySumRowHeader){return _SumRowHeaderText;}else{return string.Empty;}}set{if (string.IsNullOrEmpty(value)){_SumRowHeaderText = "合计";}else{_SumRowHeaderText = value;}}}private bool _SumRowHeaderTextBold;/// <summary>/// 合计列标题用粗体显示/// </summary>public bool SumRowHeaderTextBold{get { return _SumRowHeaderTextBold; }set { _SumRowHeaderTextBold = value; }}private string[] _SummaryColumns;/// <summary>/// 要统计的列名称或数据源绑定列名称/// </summary>public string[] SummaryColumns{get { return _SummaryColumns; }set{_SummaryColumns = value;}}private string _FormatString = "F02";public string FormatString{get { return _FormatString; }set { _FormatString = value; }}#endregion#region 私有变量private Hashtable sumBoxHash;private DataGridView dgv;private Label sumRowHeaderLabel;#endregion#region 构造函数public SummaryControlContainer(DataGridView dgv, string[] summaryColumns): this(dgv, true, "合计", false, summaryColumns){}public SummaryControlContainer(DataGridView dgv, bool displaySumRowHeader, string sumRowHeaderText,bool sumRowHeaderTextBold, string[] summaryColumns){if (dgv == null){throw new Exception("DataGridView 不能为空!");}this.dgv = dgv;_DisplaySumRowHeader = displaySumRowHeader;_SumRowHeaderText = sumRowHeaderText;_SumRowHeaderTextBold = sumRowHeaderTextBold;_SummaryColumns = summaryColumns;this.Visible = true;this.Height = dgv.RowTemplate.Height;this.Top = dgv.Height - this.Height;this.Left = dgv.Left;this.BackColor = dgv.RowHeadersDefaultCellStyle.BackColor;sumBoxHash = new Hashtable();sumRowHeaderLabel = new Label();sumRowHeaderLabel.Height = this.Height;sumRowHeaderLabel.Width = dgv.RowHeadersWidth;sumRowHeaderLabel.BackColor = dgv.RowHeadersDefaultCellStyle.BackColor;this.dgv.Resize += new EventHandler(dgv_Resize);this.dgv.Scroll += new ScrollEventHandler(dgv_Scroll);this.dgv.ColumnWidthChanged += new DataGridViewColumnEventHandler(dgv_ColumnWidthChanged);this.dgv.RowHeadersWidthChanged += new EventHandler(dgv_RowHeadersWidthChanged);this.dgv.RowsAdded += new DataGridViewRowsAddedEventHandler(dgv_RowsAdded);this.dgv.RowsRemoved += new DataGridViewRowsRemovedEventHandler(dgv_RowsRemoved);this.dgv.CellValueChanged += new DataGridViewCellEventHandler(dgv_CellValueChanged);this.dgv.DataSourceChanged += new EventHandler(dgv_DataSourceChanged);this.dgv.ColumnAdded += new DataGridViewColumnEventHandler(dgv_ColumnAdded);this.dgv.ColumnRemoved += new DataGridViewColumnEventHandler(dgv_ColumnRemoved);this.dgv.ColumnStateChanged += new DataGridViewColumnStateChangedEventHandler(dgv_ColumnStateChanged);this.dgv.ColumnDisplayIndexChanged += new DataGridViewColumnEventHandler(dgv_ColumnDisplayIndexChanged);reCreateSumBoxes();}#endregion#region 私有方法/// <summary>/// Checks if passed object is of type of integer/// </summary>/// <param name="o">object</param>/// <returns>true/ false</returns>protected bool IsInteger(object o){if (o is Int64){return true;}if (o is Int32){return true;}if (o is Int16){return true;}return false;}/// <summary>/// Checks if passed object is of type of decimal/ double/// </summary>/// <param name="o">object</param>/// <returns>true/ false</returns>protected bool IsDecimal(object o){if (o is Decimal){return true;}if (o is Single){return true;}if (o is Double){return true;}return false;}/// <summary>/// Calculate the Sums of the summary columns/// </summary>private void calcSummaries(){foreach (ReadOnlyTextBox roTextBox in sumBoxHash.Values){if (roTextBox.IsSummary){roTextBox.Tag = 0;roTextBox.Text = "0";roTextBox.Invalidate();}}if (SummaryColumns != null && SummaryColumns.Length > 0 && sumBoxHash.Count > 0){foreach (DataGridViewRow dgvRow in dgv.Rows){foreach (DataGridViewCell dgvCell in dgvRow.Cells){foreach (DataGridViewColumn dgvColumn in sumBoxHash.Keys){if (dgvCell.OwningColumn.Equals(dgvColumn)){ReadOnlyTextBox sumBox = (ReadOnlyTextBox)sumBoxHash[dgvColumn];if (sumBox != null && sumBox.IsSummary){if (dgvCell.Value != null && !(dgvCell.Value is DBNull)){if (IsInteger(dgvCell.Value)){sumBox.Tag = Convert.ToInt64(sumBox.Tag) + Convert.ToInt64(dgvCell.Value);}else if (IsDecimal(dgvCell.Value)){sumBox.Tag = Convert.ToDecimal(sumBox.Tag) + Convert.ToDecimal(dgvCell.Value);}sumBox.Text = string.Format("{0}", sumBox.Tag);sumBox.Invalidate();}}}}}}}}/// <summary>/// Create summary boxes for each Column of the DataGridView        /// </summary>private void reCreateSumBoxes(){foreach (Control control in sumBoxHash.Values){this.Controls.Remove(control);}sumBoxHash.Clear();int iCnt = 0;ReadOnlyTextBox sumBox;List<DataGridViewColumn> sortedColumns = SortedColumns;foreach (DataGridViewColumn dgvColumn in sortedColumns){sumBox = new ReadOnlyTextBox();sumBoxHash.Add(dgvColumn, sumBox);sumBox.Top = 0;sumBox.Height = dgv.RowTemplate.Height;sumBox.BorderColor = dgv.GridColor;sumBox.BackColor = dgv.DefaultCellStyle.BackColor;sumBox.ForeColor = dgv.DefaultCellStyle.ForeColor;sumBox.BringToFront();if (dgv.ColumnCount - iCnt == 1){sumBox.IsLastColumn = true;}if (SummaryColumns != null && SummaryColumns.Length > 0){for (int iCntX = 0; iCntX < SummaryColumns.Length; iCntX++){if (SummaryColumns[iCntX] == dgvColumn.DataPropertyName ||SummaryColumns[iCntX] == dgvColumn.Name){sumBox.TextAlign = TextHelper.TranslateGridColumnAligment(dgvColumn.DefaultCellStyle.Alignment);sumBox.IsSummary = true;sumBox.FormatString = dgvColumn.DefaultCellStyle.Format;if (dgvColumn.ValueType == typeof(System.Int32) || dgvColumn.ValueType == typeof(System.Int16) ||dgvColumn.ValueType == typeof(System.Int64) || dgvColumn.ValueType == typeof(System.Single) ||dgvColumn.ValueType == typeof(System.Double) || dgvColumn.ValueType == typeof(System.Single) ||dgvColumn.ValueType == typeof(System.Decimal)){sumBox.Tag = System.Activator.CreateInstance(dgvColumn.ValueType);}}}}sumBox.BringToFront();this.Controls.Add(sumBox);iCnt++;}sumRowHeaderLabel.Font = new Font(dgv.DefaultCellStyle.Font, SumRowHeaderTextBold ? FontStyle.Bold : FontStyle.Regular);sumRowHeaderLabel.Anchor = AnchorStyles.Left;sumRowHeaderLabel.TextAlign = ContentAlignment.MiddleRight;sumRowHeaderLabel.Height = this.Height;sumRowHeaderLabel.Width = dgv.RowHeadersWidth;sumRowHeaderLabel.Top = 0;sumRowHeaderLabel.Text = DisplaySumRowHeader ? SumRowHeaderText : string.Empty;sumRowHeaderLabel.ForeColor = dgv.DefaultCellStyle.ForeColor;sumRowHeaderLabel.Margin = new Padding(0);sumRowHeaderLabel.Padding = new Padding(0);this.Controls.Add(sumRowHeaderLabel);calcSummaries();resizeSumBoxes();}/// <summary>/// Order the columns in the way they are displayed/// </summary>private List<DataGridViewColumn> SortedColumns{get{List<DataGridViewColumn> result = new List<DataGridViewColumn>();DataGridViewColumn column = dgv.Columns.GetFirstColumn(DataGridViewElementStates.None);if (column == null){return result;}result.Add(column);while ((column = dgv.Columns.GetNextColumn(column, DataGridViewElementStates.None, DataGridViewElementStates.None)) != null){result.Add(column);}return result;}}/// <summary>/// Resize the summary Boxes depending on the /// width of the Columns of the DataGridView/// </summary>private void resizeSumBoxes(){try{this.SuspendLayout();if (sumBoxHash != null && sumBoxHash.Count > 0)try{int rowHeaderWidth = dgv.RowHeadersVisible ? dgv.RowHeadersWidth - 1 : 0;int sumLabelWidth = dgv.RowHeadersVisible ? dgv.RowHeadersWidth - 1 : 0;int curPos = rowHeaderWidth;if (DisplaySumRowHeader && sumLabelWidth > 0){sumRowHeaderLabel.Visible = true;sumRowHeaderLabel.Width = sumLabelWidth;if (dgv.RightToLeft == RightToLeft.Yes){if (sumRowHeaderLabel.Dock != DockStyle.Right){sumRowHeaderLabel.Dock = DockStyle.Right;}}else{if (sumRowHeaderLabel.Dock != DockStyle.Left){sumRowHeaderLabel.Dock = DockStyle.Left;}}}else{if (sumRowHeaderLabel.Visible){sumRowHeaderLabel.Visible = false;}}int iCnt = 0;Rectangle oldBounds;foreach (DataGridViewColumn dgvColumn in SortedColumns){ReadOnlyTextBox sumBox = (ReadOnlyTextBox)sumBoxHash[dgvColumn];if (sumBox != null){oldBounds = sumBox.Bounds;if (!dgvColumn.Visible){sumBox.Visible = false;continue;}int from = dgvColumn.Frozen ? curPos : curPos - dgv.HorizontalScrollingOffset;int width = dgvColumn.Width + (iCnt == 0 ? 0 : 0);if (from < rowHeaderWidth){width -= rowHeaderWidth - from;from = rowHeaderWidth;}if (from + width > this.Width){width = this.Width - from;}if (width < 4){if (sumBox.Visible){sumBox.Visible = false;}}else{if (this.RightToLeft == RightToLeft.Yes){from = this.Width - from - width;}if (sumBox.Left != from || sumBox.Width != width){sumBox.SetBounds(from, 0, width, 0, BoundsSpecified.X | BoundsSpecified.Width);}if (!sumBox.Visible){sumBox.Visible = true;}}curPos += dgvColumn.Width + (iCnt == 0 ? 0 : 0);if (oldBounds != sumBox.Bounds){sumBox.Invalidate();}}iCnt++;}}finally{this.ResumeLayout();}}
#if (DEBUG)catch (Exception ee){MessageBox.Show(ee.ToString());System.Diagnostics.Debug.WriteLine(ee.ToString());}#elsecatch{ }
#endif}#endregion#region 事件处理程序void dgv_DataSourceChanged(object sender, EventArgs e){calcSummaries();}private void dgv_CellValueChanged(object sender, DataGridViewCellEventArgs e){ReadOnlyTextBox roTextBox = (ReadOnlyTextBox)sumBoxHash[dgv.Columns[e.ColumnIndex]];if (roTextBox != null){if (roTextBox.IsSummary){calcSummaries();}}}private void dgv_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e){calcSummaries();}private void dgv_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e){calcSummaries();}private void dgv_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e){//resizeSumBoxes();reCreateSumBoxes();}private void dgv_ColumnStateChanged(object sender, DataGridViewColumnStateChangedEventArgs e){resizeSumBoxes();}private void dgv_Scroll(object sender, ScrollEventArgs e){resizeSumBoxes();}private void dgv_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e){resizeSumBoxes();}private void dgv_RowHeadersWidthChanged(object sender, EventArgs e){int columnsWidth = 0;for (int iCnt = 0; iCnt < dgv.Columns.Count; iCnt++){if (dgv.Columns[iCnt].Visible){if (dgv.Columns[iCnt].AutoSizeMode == DataGridViewAutoSizeColumnMode.Fill){columnsWidth += dgv.Columns[iCnt].MinimumWidth;}elsecolumnsWidth += dgv.Columns[iCnt].Width;}}this.Width = columnsWidth;resizeSumBoxes();}protected override void OnResize(EventArgs e){base.OnResize(e);resizeSumBoxes();}private void dgv_Resize(object sender, EventArgs e){adjustSumControlToGrid();resizeSumBoxes();}private void adjustSumControlToGrid(){ScrollBar horizontalScrollBar = (ScrollBar)typeof(DataGridView).GetProperty("HorizontalScrollBar", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).GetValue(dgv, null);ScrollBar verticalScrollBar = (ScrollBar)typeof(DataGridView).GetProperty("VerticalScrollBar", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).GetValue(dgv, null);if (horizontalScrollBar.Visible){this.Top = dgv.Height - this.Height - horizontalScrollBar.Height;}else{this.Top = dgv.Height - this.Height;}this.Left = dgv.Left;if (verticalScrollBar.Visible){this.Width = dgv.Width - verticalScrollBar.Width;}else{this.Width = dgv.Width;}}private void dgv_ColumnRemoved(object sender, DataGridViewColumnEventArgs e){reCreateSumBoxes();}private void dgv_ColumnAdded(object sender, DataGridViewColumnEventArgs e){reCreateSumBoxes();}#endregion}internal partial class ReadOnlyTextBox : Control{StringFormat format;public ReadOnlyTextBox(){// InitializeComponent();format = new StringFormat(StringFormatFlags.NoWrap | StringFormatFlags.FitBlackBox | StringFormatFlags.MeasureTrailingSpaces);format.LineAlignment = StringAlignment.Center;this.Height = 10;this.Width = 10;this.Padding = new Padding(2);}public ReadOnlyTextBox(IContainer container){container.Add(this);// InitializeComponent();this.TextChanged += new EventHandler(ReadOnlyTextBox_TextChanged);}private void ReadOnlyTextBox_TextChanged(object sender, EventArgs e){if (!string.IsNullOrEmpty(formatString) && !string.IsNullOrEmpty(Text)){Text = string.Format(formatString, Text);}}private Color borderColor = Color.Black;private bool isSummary;public bool IsSummary{get { return isSummary; }set { isSummary = value; }}private bool isLastColumn;public bool IsLastColumn{get { return isLastColumn; }set { isLastColumn = value; }}private string formatString;public string FormatString{get { return formatString; }set { formatString = value; }}private HorizontalAlignment textAlign = HorizontalAlignment.Left;[DefaultValue(HorizontalAlignment.Left)]public HorizontalAlignment TextAlign{get { return textAlign; }set{textAlign = value;setFormatFlags();}}private StringTrimming trimming = StringTrimming.None;[DefaultValue(StringTrimming.None)]public StringTrimming Trimming{get { return trimming; }set{trimming = value;setFormatFlags();}}private void setFormatFlags(){format.Alignment = TextHelper.TranslateAligment(TextAlign);format.Trimming = trimming;}public Color BorderColor{get { return borderColor; }set { borderColor = value; }}protected override void OnPaint(PaintEventArgs e){int subWidth = 0;Rectangle textBounds;if (!string.IsNullOrEmpty(formatString) && !string.IsNullOrEmpty(Text)){Text = String.Format("{0:" + formatString + "}", Convert.ToDecimal(Text));}textBounds = new Rectangle(this.ClientRectangle.X + 2, this.ClientRectangle.Y + 2, this.ClientRectangle.Width - 2, this.ClientRectangle.Height - 2);using (Pen pen = new Pen(borderColor)){if (isLastColumn)subWidth = 1;e.Graphics.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);e.Graphics.DrawRectangle(pen, this.ClientRectangle.X, this.ClientRectangle.Y, this.ClientRectangle.Width - subWidth, this.ClientRectangle.Height - 1);e.Graphics.DrawString(Text, Font, Brushes.Black, textBounds, format);}}}internal static class TextHelper{public static StringAlignment TranslateAligment(HorizontalAlignment aligment){if (aligment == HorizontalAlignment.Left)return StringAlignment.Near;else if (aligment == HorizontalAlignment.Right)return StringAlignment.Far;elsereturn StringAlignment.Center;}public static HorizontalAlignment TranslateGridColumnAligment(DataGridViewContentAlignment aligment){if (aligment == DataGridViewContentAlignment.BottomLeft || aligment == DataGridViewContentAlignment.MiddleLeft || aligment == DataGridViewContentAlignment.TopLeft)return HorizontalAlignment.Left;else if (aligment == DataGridViewContentAlignment.BottomRight || aligment == DataGridViewContentAlignment.MiddleRight || aligment == DataGridViewContentAlignment.TopRight)return HorizontalAlignment.Right;elsereturn HorizontalAlignment.Center;}public static TextFormatFlags TranslateAligmentToFlag(HorizontalAlignment aligment){if (aligment == HorizontalAlignment.Left)return TextFormatFlags.Left;else if (aligment == HorizontalAlignment.Right)return TextFormatFlags.Right;elsereturn TextFormatFlags.HorizontalCenter;}public static TextFormatFlags TranslateTrimmingToFlag(StringTrimming trimming){if (trimming == StringTrimming.EllipsisCharacter)return TextFormatFlags.EndEllipsis;else if (trimming == StringTrimming.EllipsisPath)return TextFormatFlags.PathEllipsis;if (trimming == StringTrimming.EllipsisWord)return TextFormatFlags.WordEllipsis;if (trimming == StringTrimming.Word)return TextFormatFlags.WordBreak;elsereturn TextFormatFlags.Default;}}

创建和使用方法如下:

 DataGridViewPro.ShowSummary(DGV, listColName.ToArray());//其中listColName.ToArray()为需要合计的数据,另外合计列必须使用数字格式

合计列必须要使用数字格式类型如下
dgvColumn.ValueType == typeof(System.Int32) || dgvColumn.ValueType == typeof(System.Int16) ||
dgvColumn.ValueType == typeof(System.Int64) || dgvColumn.ValueType == typeof(System.Single) ||
dgvColumn.ValueType == typeof(System.Double) || dgvColumn.ValueType == typeof(System.Single) ||
dgvColumn.ValueType == typeof(System.Decimal)
设定方法如下:

  column.DataType = typeof(decimal);//设定列格式

DGV下面加入合计功能相关推荐

  1. Ureport2小计和合计功能

    原报表样式如下: 我们希望根据做小计和合计功能,希望实现的报表结果如下: 第一步: 先按要求设计如下报表: 此处主要说明三个sum(C1)的配置,基础配置不在复述,如果基础配置有问题,请查阅资料 ht ...

  2. java poi 导出中利用sum函数实现合计功能

    java poi 导出中利用sum函数实现合计功能 之前也写过导出功能但是没有写过合计.所以记录下来当做笔记. for(int i = 0; i < arrSize; i++) {JSONObj ...

  3. ALV分类合计功能实现

    鉴于网上有用的资料实在太少,只能自己学用心学点ABAP及SAP知识. 对于ABAP ALV的ALV_S_SORT排序大家一定不陌生 其字段如下 SPOS               SLIS_SPOS ...

  4. 计算机合计功能,Javascript自动求和,Javascript自动合计

    分享一个小编经常在实际项目中使用的Javascript自动求和,javascript自动合计的代码,兼容IE8.火狐和谷歌浏览器,读者自己试试IE9.IE10.IE11. 直接给代码: functio ...

  5. Extjs中GridSummary实现EditorGridPanel的合计功能

    在使用gridpanel中,可以使用插件Ext.ux.grid.GroupSummary,实现分组统计,如图所示. 但通常情况下,我们也需要不进行分组统计,直接对数据进行合计显示,如下图: 这个时候, ...

  6. jaspersoft table自动补空加末尾合计功能

    1.效果图: 2.分析 2.1 首先确定思路,先查询表中的所有记录数,然后再补相应的空行,如需固定A4 20行,则计算方式为20-$P{LEN},先来定义参数LEN 2.2 添加参数LEN 2.3 在 ...

  7. 页面多条件组合查询功能 代码 如何写效率高_Jeecg Boot 2.2 首个里程碑版本发布,低代码平台

    项目介绍 JeecgBoot是一款基于代码生成器的低代码开发平台,开源界"小普元"超越传统商业企业开发平台!采用前后端分离架构:SpringBoot 2.x,Ant Design& ...

  8. ElementUI中为table增加小计/合计

    ElementUI中只有为表格增加一个合计的功能,但是有些时候可能会遇到同时增加小计/合计的功能,可以利用slot='append'去实现多个合计功能. 文章地址: ElementUI中为table增 ...

  9. SAP R3 功能详解 - 财务管理

     1SAP R/3系统中的财会子系统 1.1企业结构的变化 企业经营管理的全球化和多元化推动了世界范围内企业结构的变化,并且使业务流程 日益复杂. 这种趋势推动了产品和业务流程的革新和对信息高速公 ...

最新文章

  1. 趋势畅想-搭载android系统的智能数码相机
  2. laravel json字段添加_Laravel 6.0.4 中将添加计划任务事件
  3. 日历控件的android代码,Android日历控件PickTime代码实例
  4. 计算机组装与维护致谢,毕业设计(论文)_计算机组装与维护 .doc
  5. MySQL常用存储引擎之Memory
  6. 前端框架 渐进式框架
  7. oracle between and monday,oracle——时间
  8. linux中将 home目录备份成,6种优化Linux系统备份的应用与技巧
  9. SmoothNLP 中文NLP文本处理工具 Python 实战示范
  10. MTK MODEM(1)--- MTK平台NV基本功能与操作
  11. win10浏览器闪退_从没法用到真香!没想到改进了 3 年的 Windows 10 浏览器,竟然这么好用...
  12. Docker Jenkins Node(一):初步构建
  13. 【开发工具】之makefile基本规则
  14. vue页面回显数据_解决vue表单回显数据无法修改的问题
  15. java操作sql数据库_Java连接Sql数据库经常用到的操作
  16. 使用python实现猴子摘香蕉问题
  17. 静下心来,无欲则刚——源自内心的骄傲
  18. 如何在iPhone/iPad上录屏
  19. 0422-团队项目开发
  20. 好消息,个税起征点要提至每月5000了!

热门文章

  1. 【串口服务器rs485通信教程】存储型网关工作模式
  2. iOS中的3种卡顿检测
  3. 叠片过滤器安装维护注意事项
  4. 零死角玩转stm32初级篇5-流水灯的前后今生
  5. 开除AI伦理学家,谷歌如何从“不作恶”到“不宽容”?
  6. golang使用josn.Unmarshal报错:unexpected end of JSON input
  7. 在IE中打开或下载文件
  8. 机器学习算法各个击破
  9. 遗传图谱的可视化(比mapchart更强大)
  10. 安全风险 microsoft 已阻止宏运行 因为此文件的来源不受信任