QA@IT
この質問・回答は、@ITの旧掲示板からインポートされたものです。

CSV ⇒ EXCEL エクセルファイルを確認すると「001」が「1」と表示されます。

◎やりたいこと

  C#でCSVファイルをEXCElファイルに変換したい。
  (OS⇒WindowsS 2003 Server、Excel⇒2000)

●現象
  エクセルファイルを確認すると「001」が「1」と表示されます。

★現コード↓
Excel.Application excel = null;
excel = new Excel.Application();
Excel.Workbook workbook = excel.Workbooks.Add("CSVファイルのパス")
excel.Visible = true;

どなたかご教授頂けないでしょうか。
よろしくお願いいたします。

[ メッセージ編集済み 編集者: yama 編集日時 2006-01-11 01:18 ]

質問者:yama

回答

まずは、前スレとリンクしましょう。

  CSV=>EXCEL

前スレで Range の使い方を提示しましたが、状況は変わらず... ですか。
そして、COM オブジェクトの使い方の誤りも直っていませんね...

_________________C# と VB.NET の入門サイト
じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

yamaさんの書き込み (2006-01-11 00:53) より:

●現象

  エクセルファイルを確認すると「001」が「1」と表示されます。

仕様です。そもそもCSVファイルには表示書式に関する情報は含まれていません。Excelは文字列を型を自動認識した上で、標準書式を用いてこれを表示しようとします。もし001と表示して欲しいなら、表示書式を明示的に指定するか、文字列として処理するように指定する必要があるでしょう。

投稿者:甕星

編集 履歴 (0)

なので、Excel Book 形式で保存したいってことだと思いますけど...
違うのかな...?

_________________C# と VB.NET の入門サイト
じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

CSVデータのそれぞれの先頭にタブをつけると文字列として認識されるようになります。

投稿者:Anthyhime

編集 履歴 (0)

末尾タブでもいいです、x7F なども使えます、データには混入してますが。

="001",="002",="003"

でもいいです、Excelの読み込みの「仕様」ですからどうしようもありません。

手操作では
1.CSVではなくTSVの TAB区切りにする
2.新規シートで列書式を設定しておく(マクロなど)
3.そこに、TSVをコピペする。
[ メッセージ編集済み 編集者: MMX 編集日時 2006-01-11 19:31 ]

投稿者:MMX

編集 履歴 (0)

[データ]-[外部データの取り込み]-[テキスト ファイルのインポート]を
マクロで記録してみて下さい。

投稿者:soluna

編集 履歴 (0)

お世話になります。

yamaさんの書き込み (2006-01-11 00:53) より:

◎やりたいこと

  C#でCSVファイルをEXCElファイルに変換したい。

  (OS⇒WindowsS 2003 Server、Excel⇒2000)

●現象

  エクセルファイルを確認すると「001」が「1」と表示されます。

こういうことでしょうか...?
※ C# についてはあまり詳しくないです...。
※ COMオブジェクトの開放はじゃんぬさんのページを参考になさって下さい。



private void button2_Click(object sender, System.EventArgs e){
  using(System.IO.StreamReader sr = new System.IO.StreamReader(@"D:\test.csv", System.Text.Encoding.Default)){
    try{
      Excel.Application excelApp = null;
      Excel.Workbooks   excelBooks = null; 
      Excel.Workbook    excelBook = null;
      Excel.Sheets      excelSheets = null;
      Excel.Worksheet   excelSheet = null;
      Excel.Range       excelCells = null;
      Excel.Range       excelRange = null;
      try{
        excelApp    = new Excel.Application();
        excelApp.Visible = false;
        excelApp.DisplayAlerts = false;

        excelBooks  = excelApp.Workbooks;
        excelBook   = excelBooks.Add(string.Empty);
        excelSheets = excelApp.Worksheets;
        excelSheet  = (Excel.Worksheet)excelSheets[1];
        excelCells  = excelSheet.Cells;
        excelRange  = null;
        int rowCounter = 1;
        while(sr.Peek() > -1){
          string[] lines = sr.ReadLine().Split(',');
          int colCounter = 1;
          foreach (string str in lines){
            excelRange = (Excel.Range)excelCells[rowCounter, colCounter];
            excelRange.NumberFormatLocal = "@";
            excelRange.Value2 = str;
            this.releaseCom(excelRange);
            colCounter++;
          }
          rowCounter++;
        }
        excelSheet.SaveAs( @"D:\test.xls", 
                   Type.Missing, 
                   Type.Missing, 
                   Type.Missing, 
                   Type.Missing, 
                   Type.Missing, 
                   Type.Missing, 
                   Type.Missing, 
                   Type.Missing, 
                   Type.Missing);
        excelBook.Close(Type.Missing ,Type.Missing, Type.Missing);
        excelApp.Quit();
      }finally{
        this.releaseCom(excelRange);
        this.releaseCom(excelSheet);
        this.releaseCom(excelSheets);
        this.releaseCom(excelBook);
        this.releaseCom(excelBooks);
        this.releaseCom(excelApp);
      }
    }finally{
      if (sr != null) sr.Close();
    }
  }
}
private void releaseCom(object obj){
  try{
    System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
  }catch{}
}

投稿者:なおこ(・∀・)

編集 履歴 (0)

なおこ(・∀・)さんの書き込み (2006-01-11 16:49) より:

正規の方法をひとつのメソッドに実装しようとすると、かなり悲惨ですね。(^^;)




    private static void OneMethod() {
        Excel.Application xlApplication = null;

        try {
            xlApplication = new Excel.Application();
            xlApplication.SheetsInNewWorkbook = 1;
            Excel.Workbooks xlBooks = null;

            try {
                xlBooks = xlApplication.Workbooks;
                Excel.Workbook xlBook = null;

                try {
                    string stFilePath = System.IO.Path.Combine("D" + System.IO.Path.VolumeSeparatorChar, "MakiMakiLove.csv");
                    xlBook = xlBooks.Add(System.Reflection.Missing.Value);
                    Excel.Sheets xlSheets = null;

                    try {
                        xlSheets = xlBook.Sheets;
                        Excel.Worksheet xlSheet = null;

                        try {
                            xlSheet = (Excel.Worksheet)xlSheets[1];
                            Excel.Range xlCells = null;

                            try {
                                xlCells = xlSheet.Cells;

                                using (System.IO.StreamReader sr = new System.IO.StreamReader(stFilePath, System.Text.Encoding.Default)) {
                                    try {
                                        int iRow = 1;

                                        while (sr.Peek() >= 0) {
                                            string[] stLines = sr.ReadLine().Split(',');
                                            int iColumn = 1;

                                            foreach (string stItem in stLines) {
                                                Excel.Range xlRange = null;

                                                try {
                                                    xlRange = (Excel.Range)xlCells[iRow, iColumn];
                                                    xlRange.NumberFormatLocal = "@";
                                                    xlRange.Value2 = stItem;
                                                    iColumn++;
                                                } finally {
                                                    if (xlRange != null) {
                                                        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRange);
                                                    }
                                                }
                                            }

                                            iRow++;
                                        }
                                    } finally {
                                        if (sr != null) {
                                            sr.Close();
                                        }
                                    }
                                }
                            } finally {
                                if (xlCells != null) {
                                    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlCells);
                                }
                            }
                        } finally {
                            if (xlSheet != null) {
                                System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheet);
                            }
                        }
                    } finally {
                        if (xlSheets != null) {
                            System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheets);
                        }
                    }

                    xlBook.SaveAs (
                        System.IO.Path.ChangeExtension(stFilePath, "xls"),
                        System.Reflection.Missing.Value, System.Reflection.Missing.Value,
                        System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value,
                        Excel.XlSaveAsAccessMode.xlNoChange, System.Reflection.Missing.Value, System.Reflection.Missing.Value,
                        System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value
                    );
                } finally {
                    if (xlBook != null) {
                        try {
                            xlBook.Close(System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
                        } finally {
                            System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook);
                        }
                    }
                }
            } finally {
                if (xlBooks != null) {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks);
                }
            }
        } finally {
            if (xlApplication != null) {
                try {
                    xlApplication.Quit();
                } finally {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication);
                }
            }
      }
    }

疲れました... orz

_________________C# と VB.NET の入門サイト
じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

ねぇねぇ、これって、シート全体を文字列フィールドに変えちゃダメなの?
マクロで記録できると思うんだけど・・・?

もし、局所的なマスだけに影響を及ぼしたいなら、
strTemp2 = int(strTemp)
if ( strTemp != strTemp2) {
  局所的に文字列フィールド
}

こんな処理で何とかなりません?

投稿者:るぱん

編集 履歴 (0)

るぱんさんの書き込み (2006-01-12 00:23) より:

ねぇねぇ、これって、シート全体を文字列フィールドに変えちゃダメなの?

マクロで記録できると思うんだけど・・・?

CSV には書式なんて存在しませんよ。
やるならば、Excel Book 形式などにする必要があります。
だからこそ、元質問者さんは変換しようとされたんだと思ってるんですが。

もし、局所的なマスだけに影響を及ぼしたいなら、

strTemp2 = int(strTemp)

if ( strTemp != strTemp2) {

  局所的に文字列フィールド

}

このコードの意図が判りませんでした...

_________________C# と VB.NET の入門サイト
じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

yamaさんの書き込み (2006-01-11 00:53) より:

◎やりたいこと

  C#でCSVファイルをEXCElファイルに変換したい。

  (OS⇒WindowsS 2003 Server、Excel⇒2000)

●現象

  エクセルファイルを確認すると「001」が「1」と表示されます。

★現コード↓

Excel.Application excel = null;

excel = new Excel.Application();

Excel.Workbook workbook = excel.Workbooks.Add("CSVファイルのパス")

excel.Visible = true;

どなたかご教授頂けないでしょうか。

よろしくお願いいたします。

このソースコードを見る限り、
ExcelWorkBookにCSVを突っ込んでると思うのですが・・・?

CSVファイルをエクセルファイル化してますよね?
って、文意を読み違えてるのかな?
Excelに持ってくるだけなら
Excel側の各セルの書式を変えてやれば良いんじゃないですか?って意味です。

コードは以下の間違いでした。
ごめんなさい。

strTemp2 = str(int(strTemp) )
if ( strTemp != strTemp2) {
  局所的に文字列フィールド
}

int関数とかstr関数がC#に用意されてるかは理解してないのですが、
CSVの一つのValueを評価したらいいと思うのですが?
ダメですかね?

投稿者:るぱん

編集 履歴 (0)

るぱんさんの書き込み (2006-01-12 01:06) より:

このソースコードを見る限り、

ExcelWorkBookにCSVを突っ込んでると思うのですが・・・?

はい、そうですね。

CSVファイルをエクセルファイル化してますよね?

いいえ、していません。
何もしていませんから「化」けることはできません。

Excelに持ってくるだけなら

Excel側の各セルの書式を変えてやれば良いんじゃないですか?って意味です。

出来るんでしょうか?

Excel.Workbook.Open メソッドは、あくまでも Excel アプリケーションから、
書式なし (メモ帳レベル) のファイルを読み込んでいるだけです。

読み込んだ時点で書式は失われて、"001" は 1 になりますが、どうやって元の "桁数" を復元すれば良いでしょうか?

コードは以下の間違いでした。

ごめんなさい。

strTemp2 = str(int(strTemp) )

if ( strTemp != strTemp2) {

  局所的に文字列フィールド

}

数値型に置き換えて、再度文字列にすることでカンマを除いているってことでしょうか。
キャスト前の検証の有無に関わらず、キャストというものは高コストです。
String.Replace メソッドで取り除くべきだと思います。

int関数とかstr関数がC#に用意されてるかは理解してないのですが、

私は VB にはあまり詳しくないのですが、
int と str 関数はキャストとは無関係ではないかと思います。
(リファレンスを見てください、CInt, CStr とは全く別物です)

CSVの一つのValueを評価したらいいと思うのですが?

ダメですかね?

桁数決め打ちで良いのであれば、Text の形成だけでいけますね。
あとは、FileFormat を Excel Book 形式で保存すれば良いです。

_________________C# と VB.NET の入門サイト
じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

CSVと言うデータを表示するI/Fにエクセルを使っていると解釈しました。
それをもって、エクセルファイル化した・・・と意識しています。

CSVをそのままつっこむのではなく、
エクセルを開いてから各セルにプロットしてやれば良いでしょう。

エクセルを開いた後、
エクセルのシートに対して全てのセルを「文章」が入るようにセットしてやります。
その上で、CSVのデータを配列に取り込んでから各セルに流し込んでやれば良いと思いますが・・・?

開いた後に.csvと言う拡張子で保存してやれば、いいのではないかなぁ?と。
まぁ、"で括ってやる方が楽ですけどね。

まぁ、その後、CSVを何処かへ持っていくとなると難しいか・・・?

えっと、キャストなんて高等な思想はVBにとっては邪道です。
ただ、ひたすら配列をガリガリ扱うんですよ。(笑)

できるかできないかと言われれば出来なくは無い・・・かな?

strTemp2 = str(int(strTemp) )
上記はJavaで表現すると
String strTemp2 = (Integer.parseInt(strTemp)).toString()
こんな感じです。

コレってキャストですか?
001を見分けたい時にコレで取れませんかね?

投稿者:るぱん

編集 履歴 (0)

るぱんさんの書き込み (2006-01-12 09:14) より:

CSVと言うデータを表示するI/Fにエクセルを使っていると解釈しました。

それをもって、エクセルファイル化した・・・と意識しています。

先にも書きましたが、CSV ファイルを Excel アプリケーションで開いているだけです。
少なくとも、エクセルファイルではないでしょう。

CSVをそのままつっこむのではなく、

エクセルを開いてから各セルにプロットしてやれば良いでしょう。

先にも書きましたが、何桁であるかも不明な状態で "1" を "001" に復元はできないでしょう。

エクセルを開いた後、

エクセルのシートに対して全てのセルを「文章」が入るようにセットしてやります。

その上で、CSVのデータを配列に取り込んでから各セルに流し込んでやれば良いと思いますが・・・?

ロジックに関しては具体的に仰ってください。
この文章をも、私は誤解してそうな気がします。

"何を" Excel で開いた後ですか?
各セルへの再セットは、すでになおこさんも私も実装例をあげています。

CSV ファイルを Excel アプリケーションから開くと "001" は "1" と見なされます。
Cell の参照でかなり処理速度も落ちますし、さらにムダに COM オブジェクトを扱うのは避けたいという事実があります。

開いた後に.csvと言う拡張子で保存してやれば、いいのではないかなぁ?と。

まぁ、"で括ってやる方が楽ですけどね。

すいません、意味が判りませんでした。
CSV ファイルを開いた後に、.csv という拡張子で保存しても何も変わらないと思いますが...

まぁ、その後、CSVを何処かへ持っていくとなると難しいか・・・?

?????
元ファイルを削除する必要はないと思います。
普通に Extension が変わってしまいますからね。
(でないと、別のアプリケーションで正しく扱えない)

えっと、キャストなんて高等な思想はVBにとっては邪道です。

キャストは「高等な思想」ではないでしょう。
また、VB だからダメという根拠が判りません。
キャストを避けるべきなのはどの言語でも変わりません。

ただ、ひたすら配列をガリガリ扱うんですよ。(笑)

るぱんさんの仰ることが、判らないことが多々あります。
キーワードを並べただけでは、私には理解できません。
できれば、具体例をあげてください。

できるかできないかと言われれば出来なくは無い・・・かな?

(snip)

コレってキャストですか?

001を見分けたい時にコレで取れませんかね?

繰り返しに近いですが、parseInt メソッドが成功する保証は?
先ほども申し上げたように String.Replace メソッドを使うべきです。
できるできないを私は問題にしていません。

# VB の Int 関数が parseInt メソッドの代わりだとも思っていません。

_________________C# と VB.NET の入門サイト
じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

  C#でCSVファイルをEXCElファイルに変換したい。

ってことなんで、最終成果物として欲しいのは「Excel ワークシート」なんでしょう。

てことなら、Excel で CSV ファイルを開いた後にセルの書式設定をしてやって、Save の時に保存形式を明示的に指定してやればいいんじゃないすか?

投稿者:渋木宏明(ひどり)

編集 履歴 (0)

渋木宏明(ひどり)さんの書き込み (2006-01-12 09:42) より:

Excel で CSV ファイルを開いた後にセルの書式設定をしてやって、

Save の時に保存形式を明示的に指定してやればいいんじゃないすか?

Excel.Application から CSV ファイルを開いて、
FileFormat を Excel Book に変更することで可能であることは、私も保証します。
が、"001" が "1" になることを防ぐことはできるのでしょうか?

CSV ファイルから開いた時点で、書式は失われ "1" という数字になっています。
再セットする必要があるとして、「"001" であった」ことは、Excel.Application から取得できるのでしょうか?

私は、それを焦点に当てています... (^^;)
これができるのであれば、低速なれど方法の 1 つとして選択は可能です。

_________________C# と VB.NET の入門サイト
じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)

Excel.Application から CSV ファイルを開いて、

FileFormat を Excel Book に変更することで可能であることは、私も保証します。

が、"001" が "1" になることを防ぐことはできるのでしょうか?

CSV ファイルから開いた時点で、書式は失われ "1" という数字になっています。

でしたっけ?

ワークブックを保存するまでは、セルデータは 001 で、書式のせいで 1 になってるもんだと勘違いしてました (^^;

となると、「CSV を Excel で開いてから」どうこうする戦略は×ですね。

CSVのデータをプログラムで読み込んで、新規で開いたワークブックのセルに1個ずつ書式とともにセットするか、Excel をオートメーションして書式付でとりこませるかの2つくらいしか道はないかな?

投稿者:渋木宏明(ひどり)

編集 履歴 (0)

CSV ファイルから開いた時点で、書式は失われ "1" という数字になっています。

再セットする必要があるとして、「"001" であった」ことは、Excel.Application から取得できるのでしょうか?

Workbooks.Open を用いた場合には、数値(Double)として取り込まれますので、
無理です。

簡単にやりたいのであれば、既出ですが拡張子を ".txt" に Rename してから
OpenText Method で取り込む。

あとは、Cell の書式設定を文字列にしておいて、
Workbooks.Open とは別の手段を用いてゴリゴリと
Cell に Set するとか。

ちなみに、VBA とかであれば、一度 String 型の変数に Set すれば、
文字列で取り込まれますが、.NET ではどうなのでしょうかね?

投稿者:ちゃっぴ

編集 履歴 (0)

Excel.QueryTableを使うと書式付けて読めますよ。

投稿者:ジブ

編集 履歴 (0)

ちゃっぴさんの書き込み (2006-01-12 10:25) より:

簡単にやりたいのであれば、既出ですが拡張子を ".txt" に Rename してから

OpenText Method で取り込む。

実は、OpenText メソッドは先ほどからこっそり試していました。(^^;)
Extension を .txt に変えると 1 つのデータとして見なされるので、
Delimiter をカンマであることを明示化する必要がありますね。

そして、それよりももっと重要なのは、FieldInfo の指定をせねばならないことですね。
指定しなければ、問題は CSV の時のままです。

# これが判らなかった...




    xlBooks.OpenText (
        stFilePath, System.Reflection.Missing.Value, System.Reflection.Missing.Value,
        Excel.XlTextParsingType.xlDelimited, Excel.XlTextQualifier.xlTextQualifierDoubleQuote,
        System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, true,
        System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value,
        new object[] {1, 2, 2, 2, 3, 2},
        System.Reflection.Missing.Value, System.Reflection.Missing.Value,
        System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value
    );

こんな感じでいけそうです。(多分)

ちなみに、VBA とかであれば、一度 String 型の変数に Set すれば、

文字列で取り込まれますが、.NET ではどうなのでしょうかね?

はい、置き換えれば OK ですね。
ベタに "001" とかを設定すると、"001" として保持されます。

あー、調べ疲れました...

_________________C# と VB.NET の入門サイト
じゃんぬねっと日誌

投稿者:じゃんぬねっと

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。