【问题标题】:Convert xlxs to csv and Data Format将 xlxs 转换为 csv 和数据格式
【发布时间】:2020-05-09 14:06:00
【问题描述】:

我在转换文件时遇到了两个问题:

  1. 我希望日期格式如下所示:
19.08.2019

它看起来像这样

8/19/2019

2. 转换后,在 csv 文件中添加了带逗号的附加行。我该如何克服呢?

11,900011,S1,8/19/2019,11,6.90,9.90,,18.50,,8.80,,,,,,,,,,,,,,,,,,,,,,,,
12,900012,S1,8/19/2019,12,6.70,8.80,,14.50,,9.40,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
....

我使用图书馆

using Excel=Microsoft.Office.Interop.Excel;

这是我的代码:

 public static void Convert()
        {
            try
            {
                Excel.Application app = new Excel.Application();
                //Load file . xlsx
                Excel.Workbook wb = app.Workbooks.Open(Program.filePaths[1]);
                //Save file .csv
                wb.SaveAs(Program.filePaths[0], Excel.XlFileFormat.xlCSVWindows, Type.Missing, Type.Missing, false, false, Excel.XlSaveAsAccessMode.xlNoChange, Excel.XlSaveConflictResolution.xlLocalSessionChanges, false, Type.Missing, Type.Missing, Type.Missing);
                wb.Close(false);
                app.Quit();


            }catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }


        }

提前感谢您的帮助

【问题讨论】:

    标签: c# .net excel save converters


    【解决方案1】:

    我使用 npoi 从 excel 转换为 csv npoi (对不起,因为那里丢失了字符串,这是我项目的副本)

            public Dictionary<string, string> ExceltoCsv(IWorkbook input)
        {
            var csvTrennzeichen = OutputSettings.ColumnSeparator.ToString();
            var result = new Dictionary<string, string>();
            for (var sheetIndex = 0; sheetIndex < input.NumberOfSheets; sheetIndex++)
            {
                var sheet = input.GetSheetAt(sheetIndex);
                var sheetresult = new List<string>();
                for (var row = sheet.FirstRowNum; row < sheet.LastRowNum; row++)
                {
                    var rowObj = sheet.GetRow(row);
                    if (rowObj.Cells.All(x => string.IsNullOrEmpty(WertAuslesen(x))))
                        continue;
    
                    var line = string.Join(csvTrennzeichen, rowObj.Cells
                                                            .Select(cell => WertAuslesen(cell).Replace("\r", " ").Replace("\n", " "))
                                                            .Select(cell => OutputSettings.Writeinquotes ? string.Format("\"{0}\"", cell.Replace("\"", "\"\"")) : cell));
    
                    sheetresult.Add(line);
                }
    
                result.Add(sheet.SheetName, string.Join("\r\n", sheetresult));
            }
            return result;
        }
    
        private string WertAuslesen(ICell oldCell)
        {
            switch (oldCell.CellType)
            {
                case CellType.Boolean:
                    return oldCell.BooleanCellValue.ToString();
                case CellType.Error:
                    return oldCell.ErrorCellValue.ToString();
                case CellType.Formula:
                    return oldCell.CellFormula;
                case CellType.Numeric:
                    return !DateUtil.IsCellDateFormatted(oldCell)
                        ? oldCell.NumericCellValue.ToString(OutputSettings.GetDecimalFormat(Digits(oldCell.CellStyle.GetDataFormatString())))
                        : oldCell.DateCellValue.ToString(OutputSettings.DateFormat);
                case CellType.String:
                    return oldCell.RichStringCellValue.ToString();
                case CellType.Unknown:
                    return oldCell.StringCellValue;
                default:
                    return "";
            }
        }
    
        private static int Digits(string format)
        {
            var digits = format.ContainsAny(',', '.') ? format.Split(new[] { ',', '.' }).Last() : "";
            return digits.Length;
        }
    

    我也觉得有必要添加 outputsettings 类,因为它可以解决问题,但不是必需的

        public class OutputSettings
    {
        public static readonly OutputSettings Default = new OutputSettings(Encoding.UTF8, null, "yyyyMMdd", "hh:mm:ss", ".", "", "y", "n", ',', true, "", null);
        //I am immutable
        public OutputSettings(CultureInfo culture) : this(
            Encoding.UTF8,
            null,
            culture.DateTimeFormat.ShortDatePattern,
            culture.DateTimeFormat.LongTimePattern,
            culture.NumberFormat.NumberDecimalSeparator,
            culture.NumberFormat.NumberGroupSeparator,
            "y",
            "n",
            ',',
            true,
            "",
            null)
        {
        }
    
        public OutputSettings(
            Encoding encoding,
            Version ioVersion,
            string dateFormat,
            string timeFormat,
            string decimalSeperator,
            string thousandSeperator,
            string yesString,
            string noString,
            char columnseperator,
            bool writeinquotes,
            string outputFolder,
            IResourceHandler resourceHandler)
        {
            Encoding = encoding;
            IOVersion = ioVersion;
            DateFormat = dateFormat;
            TimeFormat = timeFormat;
            DecimalSeperator = decimalSeperator;
            ThousandSeperator = thousandSeperator;
            YesString = yesString;
            NoString = noString;
            ColumnSeparator = columnseperator;
            Writeinquotes = writeinquotes;
            OutputFolder = outputFolder;
            ResourceHandler = resourceHandler;
        }
    
        public IResourceHandler ResourceHandler { get; }
    
        public Encoding Encoding { get; }
    
        public Version IOVersion { get; }
    
        public string DateFormat { get; }
    
        public string TimeFormat { get; }
    
        public string DateTimeFormat => DateFormat + " " + TimeFormat;
    
        public string DecimalSeperator { get; }
    
        public string ThousandSeperator { get; }
    
        public string DecimalFormat => GetDecimalFormat(2);
    
        public string YesString { get; }
    
        public string NoString { get; }
    
        private char _columnseperator;
        public char ColumnSeparator
        {
            get
            {
                return _columnseperator;
            }
            private set
            {
                if (value != ',' && value != ';')
                    throw new ArgumentException(Localization.Resources.StaticTranslationResource.IO_SEPARATOR_MUSS_COMMA_ODER_SEMICOLON_SEIN);
                _columnseperator = value;
            }
        }
    
        public bool Writeinquotes { get; }
        public string OutputFolder { get; set; }
    
        public string GetDecimalFormat(int precision)
        {
            if (precision < 0)
                throw new ArgumentException(Localization.Resources.StaticTranslationResource.OUTPUT_ANZAHL_DER_STELLEN_DARF_NICHT_NEGATIV_SEIN, nameof(precision));
    
            var sb = new StringBuilder($"#{ThousandSeperator}##0{DecimalSeperator}");
            if (precision == 0)
            {
                sb.Append('#');
            }
            else
            {
                for (int i = 0; i < precision; i++)
                {
                    sb.Append('0');
                }
            }
            return sb.ToString();
        }
    }
    

    编辑:我使用了很多扩展方法来使我的代码可读 containsany 就是其中之一

            public static bool ContainsAll<T>(this IEnumerable<T> superset, params T[] subset) => !subset.Except(superset).Any();
    
        public static bool ContainsAll<T>(this IEnumerable<T> superset, IEnumerable<T> subset) => !subset.Except(superset).Any();
    
        public static bool ContainsAny<T>(this IEnumerable<T> superset, params T[] subset) => subset.Any(superset.Contains);
    
        public static bool ContainsAny<T>(this IEnumerable<T> superset, IEnumerable<T> subset) => subset.Any(superset.Contains);
    

    【讨论】:

    • 非常感谢,但不幸的是我需要一个使用“Excel = Microsoft.Office.Interop.Excel;”的函数。你有什么想法吗?
    • 好吧,您可以使用我使用的相同 sheme,通过遍历列和行,excel interop 应该告诉您工作表的尺寸,然后加入字符串
    • 或重新打开 csv,删除尾随的空行并用正则表达式替换日期分隔符,例如: Regex.Replace(wholeCsvAsString, "([0-9][0-9]?)\/([ 0-9][0-9]?)\/([0-9][0-9][0-9][0-9])","$2.$1.$3")
    【解决方案2】:

    关于日期,如果您的日期在 Excel 中的格式正确,则 Excel 在导出为 CSV 时应遵循该格式。我认为它不会破坏您现有的格式;它只是按原样导出,对吗?

    Excel.Worksheet sheet = wb.ActiveSheet;
    sheet.Columns[4].NumberFormat = "yyyy.mm.dd";
    

    就额外的列/行而言...这意味着这些单元格中有“某些东西”,即使它只是格式化。如果您执行列/行删除,当您保存为 CSV 时,它会阻止它们被导出。

    如果您不知道那里有什么,那么简单的方法是找到包含“真实”数据的最后一行,这取决于您知道如何定义它......也许任何没有内容的行A、B、E列。取最后一行之后的行,删除UsedRange.最后一行的所有内容

    或者,您可以使用 Excel 中内置的 CountA 函数,该函数应该非常快。如果函数对该行返回 0,则您可以指望该行的任何单元格中都没有任何内容。快速示例:

    Excel.Range last = sheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell,
        Type.Missing);
    
    for (int row = last.Row; row > 0; row++)
    {
        Excel.Range r = (Excel.Range)sheet.Cells[row, 1];
        double o = addIn.Application.WorksheetFunction.CountA(r.EntireRow);
        if (o == 0)
            r.EntireRow.Delete();
    }
    

    未经测试,但应该是 99%... 我认为您需要自下而上,但不是 100% 确定。我的想法是,如果你不这样做,它会在删除时跳过行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-09
      • 1970-01-01
      • 2019-05-08
      • 2019-03-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多