【问题标题】:C# - Excel Number Formatting Issue with International settingsC# - 国际设置的 Excel 数字格式问题
【发布时间】:2010-11-24 15:23:34
【问题描述】:

我正在尝试使用 c# 3.5 写入 Excel 2003 电子表格。但是,我无法让它在不同的国家/地区设置中正常运行。国家/地区设置为英语或德语。这两个设置有不同的十进制和千位设置。除非用户在选项屏幕的国际设置中更改了小数点和千位分隔符,否则一切正常。任何人都可以提供帮助,因为我觉得我再也看不到树木了,并且遗漏了一些明显的东西。

总结:

从访问数据库中检索到的数据。 由 c# 应用程序读取并写入 Excel 电子表格。

Excel 2003 版 机器是英语或德语。 Excel 的国际设置选项中的小数点和千位分隔符可能已更改 -- 这就是问题所在。

观察到的行为:
带有默认选项的英语设置 --> 国际 - 符合预期
带有默认选项的德语设置 --> 国际 - 符合预期

英文设置,小数分隔符更改为“,”,千位分隔符设置为“.”和系统分隔符取消勾选选项 - > 国际 - Excel 数据不正确。请参阅带星号的行。

数据 Excel

3706888.0300 3706888.03
2587033.8000 2587033.8
2081071.1800 2081071.18
9030160.3333 90.301.603.333**
42470.9842 424.709.842**
4465546.2800 4465546.28
1436037.3200 1436037.32
111650.0000 111650
2567007.0833 25.670.070.833**

我已附上示例代码来演示此行为。如果有人能告诉我我做错了什么,将不胜感激。

要运行此代码示例,只需创建一个新的 Windows 窗体应用程序并将以下代码发布到 Form1.cs 中。您还需要添加对 Microsoft.Office.Interop.Excel 的引用。

非常感谢

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.Threading; 
using System.Globalization;


namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public void ExportDTToExcel()
        {

            Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
            app.Visible = true;
            Workbook wb = app.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
            Worksheet ws = (Worksheet)wb.ActiveSheet;


            string culture = System.Threading.Thread.CurrentThread.CurrentCulture.ToString();//"en-GB";
            CultureInfo ci = new CultureInfo(culture);

            string excelGroupSeparator = app.ThousandsSeparator.ToString();
            string excelDecimalSeparator = app.DecimalSeparator.ToString();
            bool systemseparators = app.UseSystemSeparators  ;
            if (app.UseSystemSeparators == false)
            {
                app.DecimalSeparator = ci.NumberFormat.NumberDecimalSeparator;
                app.ThousandsSeparator = ci.NumberFormat.NumberGroupSeparator;
                //ci.NumberFormat.NumberDecimalSeparator = app.DecimalSeparator;
                //ci.NumberFormat.NumberGroupSeparator = app.ThousandsSeparator;
            }
            //app.DecimalSeparator = ci.NumberFormat.NumberDecimalSeparator;
            //app.ThousandsSeparator = ci.NumberFormat.NumberGroupSeparator;


            app.UseSystemSeparators = true;


            // Content.   

            try
            {
                SetCellValue("3706888.0300", ws, 0, 0, ci);
                SetCellValue("2587033.8000", ws, 1, 0, ci);
                SetCellValue("2081071.1800", ws, 2, 0, ci);
                SetCellValue("9030160.3333", ws, 3, 0, ci);
                SetCellValue("42470.9842", ws, 4, 0, ci);
                SetCellValue("4465546.2800", ws, 5, 0, ci);
                SetCellValue("1436037.3200", ws, 6, 0, ci);
                SetCellValue("111650.0000", ws, 7, 0, ci);
                SetCellValue("2567007.0833", ws, 8, 0, ci);

            }
            catch (Exception e)
            {


                    MessageBox.Show(e.Message);

            }

            //wb.SaveAs(Filepath, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
            //wb.Close(false, Type.Missing, false);
            app.DecimalSeparator = excelDecimalSeparator;
            app.ThousandsSeparator = excelGroupSeparator;
            app.UseSystemSeparators = systemseparators;
            //app.Quit();
            Marshal.ReleaseComObject(app);
            Marshal.ReleaseComObject(wb);
            Marshal.ReleaseComObject(ws);
            app = null;
            wb = null;
            ws = null;


        }

        private static void SetCellValue(string data, Worksheet ws,int row, int col, CultureInfo ci)
        {


                double val;
                try
                {
                    val = Convert.ToDouble(data);
                    Console.WriteLine(val);

                }
                catch (Exception e)
                {

                    //Util.Log("Null Value ignored.", LogType.ERROR);
                    return;
                }

                try
                {
                    string s = val.ToString();
                    ws.Cells[row + 2 , col + 1] = s;

                    //Util.Log("S:" + s, LogType.ERROR);
                }
                catch
                {
                    //Util.Log("Null Value ignored.", LogType.ERROR);
                }
            }

        private void button1_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            ExportDTToExcel();
            this.Cursor = Cursors.Default;
        }
        }
    }

【问题讨论】:

  • 我刚刚扫描了您的代码,想知道为什么您将CultureInfo ci 作为方法SetCellValue 的输入,因为您没有使用它...

标签: c# excel interop formatting numbers


【解决方案1】:

在 COM 上使用 Excel 有几个限制,最重要的限制是:

  • 使用美国文化 (LCID bug)
  • 从同一个线程调用所有方法(设置为正确的区域性“en-US”)

然后您将摆脱大多数关于 Excel 自动化和本地化的零星崩溃。

【讨论】:

    【解决方案2】:

    感谢 Chris 和 Joe,我终于让代码按预期工作了。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using Microsoft.Office.Interop.Excel;
    using System.Runtime.InteropServices;
    using System.Threading; 
    using System.Globalization;
    
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            public void ExportDTToExcel()
            {
    
                Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
                app.Visible = true;
    
                string culture = System.Threading.Thread.CurrentThread.CurrentCulture.ToString();//"en-GB";
                CultureInfo ci = new CultureInfo(culture);
    
                bool systemseparators = app.UseSystemSeparators  ;
                if (app.UseSystemSeparators == false)
                {
    
                    app.UseSystemSeparators = true;
    
                }
    
                // Content.   
                Workbook wb = app.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
                Worksheet ws = (Worksheet)wb.ActiveSheet;            
                try
                {
                    SetCellValue("3706888.0300", ws, 0, 0, ci);
                    SetCellValue("2587033.8000", ws, 1, 0, ci);
                    SetCellValue("2081071.1800", ws, 2, 0, ci);
                    SetCellValue("9030160.3333", ws, 3, 0, ci);
                    SetCellValue("42470.9842", ws, 4, 0, ci);
                    SetCellValue("4465546.2800", ws, 5, 0, ci);
                    SetCellValue("1436037.3200", ws, 6, 0, ci);
                    SetCellValue("111650.0000", ws, 7, 0, ci);
                    SetCellValue("2567007.0833", ws, 8, 0, ci);
    
                }
                catch (Exception e)
                {
    
    
                        MessageBox.Show(e.Message);
    
                }
    
                app.UseSystemSeparators = systemseparators;
                Marshal.ReleaseComObject(app);
                Marshal.ReleaseComObject(wb);
                Marshal.ReleaseComObject(ws);
                app = null;
                wb = null;
                ws = null;
            }
    
            private static void SetCellValue(string data, Worksheet ws,int row, int col, CultureInfo ci)
            {
                    double val;
                    try
                    {
                        val = Convert.ToDouble(data);
                        Console.WriteLine(val);
                    }
                    catch (Exception e)
                    {
    
                        //Util.Log("Null Value ignored.", LogType.ERROR);
                        return;
                    }
    
                    try
                    {
                        string s = val.ToString();
                        ws.Cells[row + 2 , col + 1] = s;
    
                        //Util.Log("S:" + s, LogType.ERROR);
                    }
                    catch
                    {
                        //Util.Log("Null Value ignored.", LogType.ERROR);
                    }
                }
    
            private void button1_Click(object sender, EventArgs e)
            {
                this.Cursor = Cursors.WaitCursor;
                ExportDTToExcel();
                this.Cursor = Cursors.Default;
            }
    
    
        }
    }
    

    【讨论】:

      【解决方案3】:

      我没有运行你的代码,只是扫描了一下......

      第一个潜在问题:您正在检查 UseSystemSeparators,然后设置 DecimalSeparaor 和 ThousandsSeparator。

              if (app.UseSystemSeparators == false)
              {
                  app.DecimalSeparator = ci.NumberFormat.NumberDecimalSeparator;
                  app.ThousandsSeparator = ci.NumberFormat.NumberGroupSeparator;
              }
      

      紧接着,您打开了 SystemSeparators,所以上面的代码没有做任何事情,因为您打开了系统分隔符。

              app.UseSystemSeparators = true;
      

      第二个潜在问题/建议: 设置单元格值时,将其设置为双精度值而不是字符串,让Excel为您格式化数字。

      【讨论】:

      • 谢谢克里斯。我已经清理了代码,现在我已经删除了一些不必要的行。我已将它合并到我的代码中,测试团队现在正在给它一个很好的 bash。我将在下面发布工作版本。 C# 不是我的第一语言,所以尽管代码有效,但我总是乐于改进它。
      【解决方案4】:

      This KB article 以及它链接到的其他几篇知识库文章,描述了在从 .NET 自动化 Excel 时可能遇到的一些本地化问题。

      这可能有助于解释您的问题

      【讨论】:

      • 谢谢乔。您链接的文章包含我最初忽略的内容。看来(结合下面 Chris 的建议)我需要在设置 CultureInfo 后声明 Workbook 和 Worksheet 对象。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多