分享

C# 操作Excel

 ThinkTank_引擎 2015-05-26

三种读取Excel方法

---------------------------------------------------方法一

  1. /// <summary>   
  2.         /// 解析Excel,返回DataTable   
  3.         /// </summary>   
  4.         /// <param name="fileName"></param>   
  5.         /// <returns></returns>   
  6.         public static System.Data.DataTable ImpExcel(string fileName)  
  7.         {  
  8.             System.Data.DataTable dt = new System.Data.DataTable();  
  9.             try  
  10.             {  
  11.                 Microsoft.Office.Interop.Excel.Application app;  
  12.                 Workbooks wbs;  
  13.                 Worksheet ws;  
  14.                 app = new Microsoft.Office.Interop.Excel.Application();  
  15.                 wbs = app.Workbooks;  
  16.                 wbs.Add(fileName);  
  17.                 ws = (Worksheet)app.Worksheets.get_Item(1);  
  18.                      int rows = ws.UsedRange.Rows.Count;  
  19.                 int columns = ws.UsedRange.Columns.Count;  
  20.                 string bookName = ws.Name;  
  21.                  dt = LoadDataFromExcel(filePath, bookName).Tables[0];  
  22.                 //for (int i = 1; i < rows + 1; i++)   
  23.                 //{   
  24.                 //    DataRow dr = dt.NewRow();   
  25.                 //    for (int j = 1; j <= columns; j++)   
  26.                 //    {   
  27.   
  28.   
  29.                 //        _Excel.Range range = ws.get_Range(app.Cells[i, j], app.Cells[i, j]);   
  30.                 //        range.Select();   
  31.                 //        if (i == 1)   
  32.                 //            dt.Columns.Add("Columns" + j);// dt.Columns.Add(app.ActiveCell.Text.ToString())可以直接用第一行作为列名,单合并单元格后,读取出来后列名相同会报错,所以最好不用   
  33.                 //        dr[j - 1] = app.ActiveCell.Text.ToString();   
  34.                 //    }   
  35.                 //    dt.Rows.Add(dr);   
  36.                 //}   
  37.   
  38.   
  39.                
  40.                 //newdt = dt.Clone();   
  41.                 //for (int i = 0; i < dt.Rows.Count; i++)   
  42.                 //{   
  43.                 //    if (dt.Rows[i][5].ToString() != "" && dt.Rows[i][6].ToString() != "" && dt.Rows[i][7].ToString() != "" && dt.Rows[i][8].ToString() != "" || i == 0)   
  44.                 //    newdt.ImportRow(dt.Rows[i]);   
  45.                 //}   
  46.                 KillProcess(app);  
  47.                 return dt;  
  48.             }  
  49.             catch (Exception ex)  
  50.             {  
  51.                 MessageBox.Show("数据绑定Excel失败! 失败原因:"+ex.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information);  
  52.                 return dt;  
  53.             }  
  54.         }  


----------------------------------------------------方法二

  1. /// <summary>   
  2.         /// 解析Excel   
  3.         /// </summary>   
  4.         /// <param name="filePath"></param>   
  5.         /// <param name="name"></param>   
  6.         /// <returns></returns>   
  7.         public static DataSet LoadDataFromExcel(string filePath, string name)  
  8.         {  
  9.             try  
  10.             {  
  11.                 string strConn;  
  12.                 //   strConn = " Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source = " + filePath + ";Extended Properties=Excel 8.0";   
  13.                 strConn = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties='Excel 12.0 Xml;HDR=Yes;IMEX=1'";  
  14.                 OleDbConnection OleConn = new OleDbConnection(strConn);  
  15.                 OleConn.Open();  
  16.                 string sql = "SELECT * FROM [" + name + "$]";//可是更改Sheet名称,比如sheet2,等等     
  17.                 OleDbDataAdapter OleDaExcel = new OleDbDataAdapter(sql, OleConn);  
  18.                 DataSet OleDsExcle = new DataSet();  
  19.                 OleDaExcel.Fill(OleDsExcle, name);  
  20.                 OleConn.Close();  
  21.                 return OleDsExcle;  
  22.             }  
  23.             catch (Exception err)  
  24.             {  
  25.                 MessageBox.Show("数据绑定Excel失败! 失败原因:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information);  
  26.                 return null;  
  27.             }  
  28.         }  

——————————————————插入Excel

  1. /// <summary>   
  2.   /// 写入Excel文档   
  3.   /// </summary>   
  4.   /// <param name="Path">文件名称</param>   
  5.   public bool SaveFP2toExcel(string Path)  
  6.   {  
  7.    try  
  8.    {  
  9.     string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" +"Data Source="+ Path +";"+"Extended Properties=Excel 8.0;";  
  10.     OleDbConnection conn = new OleDbConnection(strConn);  
  11.     conn.Open();    
  12.     System.Data.OleDb.OleDbCommand cmd=new OleDbCommand ();  
  13.     cmd.Connection =conn;  
  14.     for(int i=0;i<fp2.Sheets [0].RowCount -1;i++)  
  15.     {  
  16.      if(fp2.Sheets [0].Cells[i,0].Text!="")  
  17.      {  
  18.       cmd.CommandText ="INSERT INTO [sheet1$] (工号,姓名,部门,职务,日期,时间) VALUES('"+fp2.Sheets [0].Cells[i,0].Text+ "','"+  
  19.        fp2.Sheets [0].Cells[i,1].Text+"','"+fp2.Sheets [0].Cells[i,2].Text+"','"+fp2.Sheets [0].Cells[i,3].Text+  
  20.        "','"+fp2.Sheets [0].Cells[i,4].Text+"','"+fp2.Sheets [0].Cells[i,5].Text+"')";  
  21.       cmd.ExecuteNonQuery ();  
  22.      }  
  23.     }  
  24.     conn.Close ();  
  25.     return true;  
  26.    }  
  27.    catch(System.Data.OleDb.OleDbException ex)  
  28.    {  
  29.     System.Diagnostics.Debug.WriteLine ("写入Excel发生错误:"+ex.Message );  
  30.    }  
  31.    return false;  
  32.   }  

  1. //新增、修改   
  2.     _Excel.Application app = new _Excel.ApplicationClass();  
  3.             app.Visible = false;  
  4.             _Excel.Workbook book = app.Workbooks.Open(UpdateExcelPath, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing);  
  5.             _Excel.Worksheet sheet = (_Excel.Worksheet)book.ActiveSheet;  
  6.             for (int i = 0; i < dt.Rows.Count; i++)  
  7.             {  
  8.                 sheet.Cells[i + 2, 1] = dt.Rows[i][0].ToString();  
  9.                 sheet.Cells[i + 2, 2] = dt.Rows[i][1].ToString();  
  10.             }  
  11.             book.Save();  
  12.             book.Close(sheet, UpdateExcelPath, System.Type.Missing);  
  13.             app.Quit();  
  14.             System.GC.Collect();  

  1. ——————————————————修改Excel的值  
  2. //修改第一行Name的值为张三   
  3. string strComm = "update [Sheet1$] set Name='张三' WHERE 工号='132'";  
  4. OleDbConnection myConn = new OleDbConnection(strConn);  
  5. myConn.Open();  
  6. OleDbCommand com = new OleDbCommand(strComm, myConn);  
  7. com.ExecuteNonQuery();  
  8. myConn.Close();  


----------------------------用流导出Excel

  1. <span style="font-size:18px;">   private void FileStream()  
  2.         {  
  3.             FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write);  
  4.             StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.GetEncoding("gb2312"));  
  5.             string html = @"C:\Documents and Settings\Administrator\桌面\1.html";  
  6.             sw.WriteLine(File.ReadAllText(html));  
  7.             sw.Close();  
  8.         }</span>  


NOPI操作Excel

----------------------------导出

  1. using _Excel = Microsoft.Office.Interop.Excel;  
  2. using System.Drawing;  
  3. using System.Reflection;  
  4. using System.Windows.Forms;  
  5. using Microsoft.Office.Interop.Excel;  
  6.         /// <summary>   
  7.         /// DataTable直接导出Excel,此方法会把DataTable的数据用Excel打开,再自己手动去保存到确切的位置   
  8.         /// </summary>   
  9.         /// <param name="dt">要导出Excel的DataTable</param>   
  10.         /// <returns></returns>   
  11.         public static void ExportExcel(System.Data.DataTable table, string savePath, bool isExit)  
  12.         {  
  13.             if (!isExit)//保存路径是否存在   
  14.                 File.Copy(System.Windows.Forms.Application.StartupPath + @"\Excel\Excel.xls", savePath);  
  15.             _Excel.Application app = new _Excel.ApplicationClass();  
  16.             if (app == null)  
  17.             {  
  18.                 throw new Exception("Excel无法启动");  
  19.             }  
  20.             app.Visible = false;  
  21.             _Excel.Workbook book = app.Workbooks.Open(savePath, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing);  
  22.             _Excel.Worksheet sheet = (_Excel.Worksheet)book.ActiveSheet;  
  23.   
  24.         for (int k = 1; k < ds.Tables[1].Rows.Count + 1; k++)  
  25.                 {  
  26.                     _Excel.Sheets xlSheets = book.Sheets as Sheets;  
  27.                     //  添加 Sheet   
  28.                     sheet = (Worksheet)xlSheets.Add(xlSheets[1], Type.Missing, Type.Missing, Type.Missing);  
  29.                 }  
  30.           for (int j = 1; j < ds.Tables[1].Rows.Count + 1; j++)  
  31.             {  
  32.      
  33.         _Excel.Range range = null;               
  34.                sheet = (_Excel.Worksheet)book.Sheets[j];          
  35.                if (!istrue)                  
  36.              sheet.Name ="123";            
  37.           else                  
  38.              sheet.Name = "345";  
  39.                 range = sheet.get_Range("A1""C3");  
  40.                 range.MergeCells = true;//合并,将1-3行和1-3列合并为一个单元格   
  41.                 range.WrapText = true;  //自动换行   
  42.                 range.EntireRow.AutoFit();//行高根据内容自动调整   
  43.                 sheet.get_Range("A1""C3").Borders[XlBordersIndex.xlEdgeBottom].LineStyle = BorderStyle.FixedSingle;//将1-3行和1-3列合并的单元格划下划线,根据[]内属性,可以设置文本上、下、左、右的的边框框   
  44.                 sheet.get_Range("A1""C3").Borders.LineStyle = BorderStyle.FixedSingle;//给整个合并的单元格加上边框   
  45.                 sheet.get_Range("A1""C3").Font.Name = "Times New Roman";//设置字体.   
  46.                  sheet.get_Range("A1""C3").Font.Size = 22;//设置字体大小   
  47.                  range.Font.Bold = true;//加粗   
  48.                  range.RowHeight = 22;//调行高   
  49.                 rang.Interior.Color = System.Drawing.Color.FromArgb(255, 204, 153).ToArgb();//加背景色   
  50.                 range = sheet.get_Range(string.Format("D{0}", 1), string.Format("F{0}", 1));  
  51.                 range.MergeCells = true;//合并,将3-5列合并为一个单元格   
  52.                range.HorizontalAlignment = XlHAlign.xlHAlignCenter;//合并后文本水平居中   
  53.                 range.VerticalAlignment = XlVAlign.xlVAlignCenter;//合并后文本竖直居中    
  54.          單個sheet里求和:  
  55.         Excel.Range range2 = sheet.get_Range("B25", Type.Missing);  
  56.         range2.Formula = "=SUM(B2:B24)";  
  57.         range2.Calculate();  
  58.   
  59.   rang = (_Excel.Range)sheet.get_Range(string.Format("G{0}", 7), string.Format("G{0}", table.Rows.Count + 7));  
  60.   rang.NumberFormatLocal = "$#,##0.00"//设置单元格格式为货币格式    
  61.         跨sheet求和:  
  62.         Excel.Worksheet wsheet1 = (Excel.Worksheet)excelSql.Worksheets.get_Item(1);  
  63.         Excel.Range range3 =wsheet1.get_Range("A23", Type.Missing);  
  64.         range3.Formula = "=Sheet3!B8+Sheet3!B12";  
  65.         range3.Calculate();  
  66.          sheet.Cells[1, 4] = ds.Tables[1].Rows[0]["FeightCode"].ToString();//给合并的列赋值   
  67.         //循环加载数据   
  68.          int startIndex = 0;  
  69.               for (int i = 0; i < ds.Tables[0].Rows.Count; i++)  
  70.                 {  
  71.                     if (ds.Tables[1].Rows[j - 1]["BoxCode"].ToString() == ds.Tables[0].Rows[i]["BoxCode"].ToString())  
  72.                     {  
  73.                     range = sheet.get_Range("b" + (15 + startIndex) + """e" + (15 + startIndex) + "");  
  74.                     range.MergeCells = true;  
  75.                     sheet.Cells[15 + startIndex, 2] = ds.Tables[0].Rows[i]["TypeName"].ToString();  
  76.                     range = (_Excel.Range)sheet.Cells[15 + startIndex, 2];  
  77.                     range.HorizontalAlignment = XlHAlign.xlHAlignCenter;  
  78.                     range.Font.Bold = true;  
  79.                     range.RowHeight = 22;  
  80.                     sheet.Cells[15 + startIndex, 6] = ds.Tables[0].Rows[i]["Qty"].ToString();  
  81.                     range = (_Excel.Range)sheet.Cells[15 + startIndex, 6];  
  82.                     range.HorizontalAlignment = XlHAlign.xlHAlignCenter;  
  83.                     range.Font.Bold = true;  
  84.                     range.RowHeight = 22;  
  85.                     sheet.Cells[15 + startIndex, 7] = ds.Tables[0].Rows[i]["UnitPrice"].ToString();  
  86.                     range = (_Excel.Range)sheet.Cells[15 + startIndex, 7];  
  87.                     range.HorizontalAlignment = XlHAlign.xlHAlignCenter;  
  88.                     range.Font.Bold = true;  
  89.                     range.RowHeight = 22;  
  90.                     sheet.Cells[15 + startIndex, 8] = ds.Tables[0].Rows[i]["Subtotal"].ToString();  
  91.                     range = (_Excel.Range)sheet.Cells[15 + startIndex, 8];  
  92.                     range.HorizontalAlignment = XlHAlign.xlHAlignCenter;  
  93.                     range.Font.Bold = true;  
  94.                     range.RowHeight = 22;  
  95.                      Image image = Picture.ReadPicture(ds.Tables[0].Rows[row][col].ToString());  
  96.                         range = sheet.get_Range(string.Format("A{0}", row * num + 29), string.Format("A{0}", row * num + 48));  
  97.                         sheet.Shapes.AddPicture(ds.Tables[0].Rows[row][col].ToString(), Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoTrue, Convert.ToSingle(range.Left) + 15 + image.Width, Convert.ToSingle(range.Top) + 5, image.Width, image.Height);   //插入图片   
  98.                     range.EntireColumn.AutoFit();  
  99.                     System.Windows.Forms.Application.DoEvents();  
  100.                     startIndex++;  
  101.                     }  
  102.                 }  
  1.             Range ran = (Range)sheet.Cells[1, 1];//Excel导出加下拉框   
  2.             ran.Validation.Add(XlDVType.xlValidateList, XlDVAlertStyle.xlValidAlertStop, XlFormatConditionOperator.xlBetween, "1,2,3""123");  
  3.             ran.Validation.InCellDropdown = true;  
  4.             ran.Validation.IgnoreBlank = true;  
  5.             ran.Value2 = "2";  
  6.                  rang = sheet.get_Range("a" + (table.Rows.Count + 3) + """r" + (table.Rows.Count + 3) + "");  
  7.                  rang.Font.Bold = true;  
  8.                  rang.Interior.Color = System.Drawing.Color.FromArgb(255, 204, 153).ToArgb();//设置单元格背景颜色   
  9.                 sheet.Columns.AutoFit();  
  10.                 sheet.Cells.EntireColumn.AutoFit();  
  11.                 sheet.Columns.EntireColumn.AutoFit();//列宽自适应。   
  12.                 //  sheet.Cells.Borders.LineStyle =BorderStyle.Fixed3D;//设置边框   
  13.                 sheet = null;  
  14.                 book.Save();  
  15.                 }  
  16.                 book.Close(sheet, savePath, System.Type.Missing);  
  17.                 app.Quit();  
  18.                 app.DisplayAlerts=false;     //保存Excel的时候,不弹出是否保存的窗口直接进行保存   
  19.                 System.GC.Collect();  
  20.                 KillProcess(app);         
  21.    
  22.          /// <summary>   
  23.         /// 导出Excel后,杀死Excel进程   
  24.         /// </summary>   
  25.         /// <param name="app"></param>   
  26.         private static void KillProcess(_Excel.Application app)  
  27.         {  
  28.             IntPtr t = new IntPtr(app.Hwnd);  
  29.             int k = 0;  
  30.             GetWindowThreadProcessId(t, out k);  
  31.             System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k);  
  32.             p.Kill();  
  33.         }  
  34.         [DllImport("User32.dll", CharSet = CharSet.Auto)]  
  35.         public static extern int GetWindowThreadProcessId(IntPtr hwnd, out   int ID);  
  1. C#导出写保护的Excel,设置某些区域可以编辑  
  2.        对Excel操作时,由于使用权限的不同,可能对表格的操作权限也不一样。EXCEL提供了保护工作表以及允许编辑单元格功能。相应的在C#中就可以对Excel表格进行操作。  
  3. 有两种方法可以实现:  
  4. 第一种:  
  5. 主要用Protect()方法保护工作表,Worksheet.Protection.AllowEditRanges设置允许编辑的单元格。  
  6. public void CreateExcel()  
  7.     {  
  8.         //创建一个Excel文件   
  9.         Microsoft.Office.Interop.Excel.Application myExcel = new Microsoft.Office.Interop.Excel.Application();  
  10.         Microsoft.Office.Interop.Excel.Workbook excelWorkbook = null;  
  11.         Microsoft.Office.Interop.Excel.Worksheet excelSheet = null;  
  12.         myExcel.Application.Workbooks.Add(true);  
  13.         //让Excel文件可见   
  14.         myExcel.Visible = true;  
  15.         myExcel.Cells[1, 4] = "普通报表";  
  16.         //逐行写入数据   
  17.         for (int i = 0; i < 11; i++)  
  18.         {  
  19.             for (int j = 0; j < 7; j++)  
  20.             {  
  21.                 //以单引号开头,表示该单元格为纯文本   
  22.                 myExcel.Cells[2 + i, 1 + j] = "'" + i;  
  23.             }  
  24.         }  
  25.         try  
  26.         {  
  27.             string excelTemp ="c:\\a.xls";         
  28.             //excelWorkbook = myExcel.Workbooks[1];   
  29.             excelWorkbook = myExcel.ActiveWorkbook;  
  30.             excelSheet = (Microsoft.Office.Interop.Excel.Worksheet)excelWorkbook.ActiveSheet;  
  31.               
  32.             //设定允许操作的单元格   
  33.             Microsoft.Office.Interop.Excel.AllowEditRanges ranges = excelSheet.Protection.AllowEditRanges;  
  34.             ranges.Add("Information",  myExcel.Application.get_Range("B2""B2"),  Type.Missing);  
  35.             //保护工作表   
  36.             excelSheet.Protect("MyPassword", Type.Missing, Type.Missing, Type.Missing,  
  37.               Type.Missing, Type.Missing, Type.Missing, Type.Missing,  
  38.              Type.Missing, Type.Missing, Type.Missing, Type.Missing,  
  39.               Type.Missing, true, Type.Missing, Type.Missing);  
  40.             //Realease the com object   
  41.             System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet);  
  42.             excelSheet = null;  
  43.   
  44.   
  45.             //Save the result to a temp path   
  46.             excelWorkbook.SaveAs(excelTemp, Excel.XlFileFormat.xlWorkbookNormal,  nullnullfalsefalse,  
  47.                                  Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing,  
  48.                                  Type.Missing, Type.Missing,Type.Missing,Type.Missing);  
  49.         }  
  50.         catch (Exception ex)  
  51.         {  
  52.             throw;  
  53.         }  
  54.         finally  
  55.         {  
  56.             if (excelWorkbook != null)  
  57.             {  
  58.                 System.Runtime.InteropServices.Marshal.ReleaseComObject(excelWorkbook);  
  59.                 excelWorkbook = null;  
  60.             }  
  61.             if (myExcel != null)  
  62.             {  
  63.                 myExcel.Workbooks.Close();  
  64.                 myExcel.Quit();  
  65.                 System.Runtime.InteropServices.Marshal.ReleaseComObject(myExcel);  
  66.                 myExcel = null;  
  67.             }  
  68.             GC.Collect();  
  69.         }  
  70.     }  
  71.  PS:借用此方法我写了个循环来设定单元格保护,没想到一直在报HRESULT:0x800A03EC 的一个异常,郁闷。  
  72.         经过一番折腾,发现 AllowEditRanges.Add方法的第一个参数名是不能够重复的,写循环的时候没注意。   
  1. 第二种:  
  2. 用locked属性,设置Locked = false 的区域就可编辑的区域  
  3. worksheet.get_Range(worksheet.Cells[1, 1], worksheet.Cells[10, 10]).Locked = false;  
  4.    //保护工作表   
  5.   worksheet.Protect("MyPassword", Type.Missing, Type.Missing, Type.Missing,  
  6.            Type.Missing, Type.Missing, Type.Missing, Type.Missing,  
  7.            Type.Missing, Type.Missing, Type.Missing, Type.Missing,  
  8.            Type.Missing, truetruetrue);  
  9.   
  10.   
  11.   
  12.   
  13.   ///        
  14.       ///   在工作表中插入行,并调整其他行以留出空间      
  15.       ///        
  16.       ///        
  17.   当前工作表     
  18.       ///        
  19.   欲插入的行索引     
  20.       private   void   InsertRows(Excel.Worksheet   sheet,   int   rowIndex)     
  21.       {     
  22.         range   =   (Excel.Range)sheet.Rows[rowIndex,   missing];           
  23.         //object   Range.Insert(object   shift,   object   copyorigin);        
  24.         //shift:   Variant类型,可选。指定单元格的调整方式。可以为下列   XlInsertShiftDirection   常量之一:      
  25.         //xlShiftToRight   或   xlShiftDown。如果省略该参数,Microsoft   Excel   将根据区域形状确定调整方式。      
  26.         range.Insert(Excel.XlInsertShiftDirection.xlShiftDown,   missing);         
  27.       }     
  28.       
  29.       ///        
  30.       ///   在工作表中删除行      
  31.       ///        
  32.       ///        
  33.   当前工作表     
  34.       ///        
  35.   欲删除的行索引     
  36.       private   void   DeleteRows(Excel.Worksheet   sheet,   int   rowIndex)     
  37.       {     
  38.         range   =   (Range)sheet.Rows[rowIndex,   missing];     
  39.         range.Delete(Excel.XlDeleteShiftDirection.xlShiftUp);     
  40.       }     
  41.       
  42.       ///        
  43.       ///   退出Excel,并且释放调用的COM资源      
  44.       ///        
  45.       private   void   Dispose()     
  46.       {     
  47.         book.Close(missing,   missing,   missing);     
  48.         app.Workbooks.Close();     
  49.         app.Quit();   }  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多