2

残念ながら、Excel は、CSV ファイルを生成するときに、画面に表示される数値を保存するため、プログラマにとってあまり使いやすいものではありません。したがって、CSV で数値がどのように表示されるかは、地域の設定とユーザーの好みによって異なります。

その結果、次のような数字になる可能性があります

2 123
3'322
1,233.44
2123,45

そして今、私は自分のプログラムでそのような CSV ファイルを処理しなければなりません。

ユーザーに CSV ファイルの作成方法を説明する以外に、この問題に対処するスマートまたは標準的な解決策はありますか? 別のデータ形式に切り替えることも選択肢の 1 つですが、どれでしょうか? Excelでネイティブにサポートされている必要があり、扱いやすい必要があります(したがって、xlsxは避けたいと思います)。

4

2 に答える 2

2

私はクライアントに同じ問題を抱えています。各列のフォーマットを明示的にExcelに伝えるcsvマクロへのエクスポートを書きました。これがコードの例です

Public Sub Export_To_CSV()
'Give excel the sheet with data to be exported to CSV

Sheets("Sheet1").Activate

'Declare your string array to be filled - currently set to 5 columns

Dim csvread(1 To 5) As String
Dim i As Integer
i = 1

Dim ObjFso
Dim StrFileName
Dim ObjFile

'Name the export csv - This will generate it in the folder you have the excel you are working with in and then names it CSVexport-Day-Month.csv

StrFileName = Application.ThisWorkbook.Path & "\CSVExport-" & Day(Date) & "-" & Month(Date) & ".csv"
Set ObjFso = CreateObject("Scripting.FileSystemObject")
'Creating a file for writing data
Set ObjFile = ObjFso.CreateTextFile(StrFileName)

'takes the headers from row 1 - set by i if different

csvread(1) = Range("A" & i).Value
csvread(2) = Range("B" & i).Value
csvread(3) = Range("C" & i).Value
csvread(4) = Range("D" & i).Value
csvread(5) = Range("E" & i).Value

'Writes the Headers

ObjFile.WriteLine (csvread(1) & "," & csvread(2) & "," & csvread(3) & "," & csvread(4) & "," & csvread(5))

i = i + 1

'Do until loop can be altered to meet your parameters

Do Until Range("A" & i).Value = 0 Or i = 1000

'format your data however you require

csvread(15) = Format(Range("A" & i).Value, "###0.00")
csvread(15) = Format(Range("B" & i).Value, "###0.00")
csvread(15) = Format(Range("C" & i).Value, "###0.00")
csvread(15) = Format(Range("D" & i).Value, "###0.00")
csvread(15) = Format(Range("E" & i).Value, "###0.00")

'write the line to the file

ObjFile.WriteLine (csvread(1) & "," & csvread(2) & "," & csvread(3) & "," & csvread(4) & "," & csvread(5))
i = i + 1
Loop

ObjFile.Close

p = MsgBox("Exported", vbOKOnly)


End Sub
于 2013-02-28T14:13:54.210 に答える
0

これまでのところ、ファイルを自分でエクスポートする以外に良い解決策は見つかりませんでしCsvWriterた (カスタム クラスですが、簡単CsvWriter.WriteItemsです。列挙可能な文字列を取得し、必要に応じてそれらを引用し、それらから csv ファイルに行を作成します。 ):

public static class CsvExporter {

    public static void ExportWorksheet (
        CsvWriter csvWriter,
        Excel.Worksheet worksheet,
        Action<int,int> reportProgressCallback = null
    ) {
        foreach (var row in WorksheetToStrings (worksheet, reportProgressCallback))
            csvWriter.WriteItems (row);
    }



    public static IEnumerable<IEnumerable<string>> WorksheetToStrings (
        Excel.Worksheet worksheet, Action<int,int> reportProgressCallback = null
    ) {
        var usedRange = worksheet.UsedRange;
        return RangeToStrings (usedRange, reportProgressCallback);
    }



    public static IEnumerable<IEnumerable<string>> RangeToStrings (
        Excel.Range range,
        Action<int,int> reportProgressCallback = null
    ) {
        if (reportProgressCallback == null)
            reportProgressCallback = (line, total) => { };

        int rowsTotal = range.Rows.Count;
        int currentRow = 0;
        foreach (var row in range.Rows) {
            ++currentRow;
            reportProgressCallback (currentRow, rowsTotal);
            var rowValues = (row as Excel.Range).Value2 as object;
            foreach (
                var convertedRow in
                convertToEnumerableOfEnumerablesOfStrings (rowValues)
            )
                yield return convertedRow;

        }
    }



    private static IEnumerable<IEnumerable<string>>
    convertToEnumerableOfEnumerablesOfStrings (
        object values
    ) {
        return  convertToEnumerableOfEnumerablesOfObjects (values)
                    .Select (
                        r => r.Select (
                            c => convertSingleValueToString (c)
                        )
                    );
    }

    private static IEnumerable<IEnumerable<object>>
    convertToEnumerableOfEnumerablesOfObjects (
        object values
    ) {
        var ary = values as object [,];
        if (ary != null)
            return convertTwoDimAryToEnumerableOfEnumerablesOfObjects (ary);

        var obj = values as object;
        if (obj != null)
            return Enumerable.Repeat<IEnumerable<object>> (
                Enumerable.Repeat<object> (obj, 1), 1
            );

        return Enumerable.Empty<IEnumerable<object>> ();
    }

    private static IEnumerable<IEnumerable<object>>
    convertTwoDimAryToEnumerableOfEnumerablesOfObjects (
        object [,] ary
    ) {
        var firstUpperBound = ary.GetUpperBound (0);
        var secondUpperBound = ary.GetUpperBound (1);
        return Enumerable.Range (1, firstUpperBound).Select (
            i => Enumerable.Range (1, secondUpperBound).Select (j => ary [i, j])
        );
    }

    private static string convertSingleValueToString (object value) {
        if ( value == null ) {
            return string.Empty;
        } else if (value is string) {
            return value as string;
        } else if (value is long) {
            return ((long) value).ToString (CultureInfo.InvariantCulture);
        } else if (value is double) {
            return ( (double) value ).ToString (CultureInfo.InvariantCulture);
        } else if (value is bool) {
            return (bool) value ? "TRUE" : "FALSE";
        } else {
            return value.ToString ();
        }
    }


}
于 2013-03-04T14:46:50.610 に答える