2011-05-13 7 views
6

に保存されていません。動機付けたいと思います。私の仕事は、Excelシートの変更を分析することですが、変更をプログラムで検出する必要があります。また、ユーザーが変更の記録を無効にした場合や、Excel-AddInがインストールされていない場合もあります。そこでMicrosoft.Interop.Excel-Libraryを使用して、シートとその中のセルにアクセスしました。C#:Microsoft.Office.Interop.Excel.RangeのIDフィールドは、問題が始まる前にExcelシート

変更点:ユーザーがデータをソートまたは移動した場合でも、移動またはコピーしても、セルごとにユニークIDを保持したいと思っていました。もちろんコピーした場合、IDはシート内で2回あり、新しい追加セルにはIDはありませんが、それは問題ありません。さらに、このIDはユーザーに表示されるべきではなく、ユーザーはそれを変更または削除できないようにすべきです。

フィールドを探して、Range-Objectが見つかりました。これは単一のセルを表すことができ、アクセス可能なメンバーが異なります。 1つの特別なフィールドが私の注意を引いた.IDフィールドは、私が探していたもののように見えた。

Guid guid = Guid.NewGuid(); 
((Range) worksheet.Cells[rowNr, columnNr]).ID = guid.ToString(); 

とも123463-fc34-c43a-a391-よう

Guid guid = Guid.Parse(((Range) worksheet.Cells[rowNr, columnNr]).ID); 

私は文字列として、この場合のGUIDで(文字列を格納することができたので、これは、完璧だった、のように読み取ることが399fc2)を読み、それを読んでください。また、セルに移動して移動したときに移動しました。

残念ながら、このIDフィールドはファイルが保存されても保持されません。その理由はわかりません。ワークブックを閉じて再オープンした後、すべてのIDがなくなったということです。

だから私の質問は、文字列(= Guid)を保持することができ、ユーザーが見ることができないRangeオブジェクトの他のメンバーがある場合です。私は名前 - メンバーとコメント - メンバーを試しましたが、どちらもユーザーに見え、簡単に変更できます。

また、シートを保存するときに、IDフィールドも保存することをExcelに伝える方法はありますか?

テスト用に、プロジェクトを作成し、Microsoft.Office.Interop.Excel-Dllへの参照を追加し、次のコードを追加します(システムにExcelがインストールされている必要があります)。これは、JUnitので実行ユニットテスト、ですが、あまりにもJUnitをせずに、それをテストするためにアサート-コマンドを削除します。

using System; 
using System.IO; 
using Microsoft.Office.Interop.Excel; 
using Excel = Microsoft.Office.Interop.Excel; 
public void AddGuidAndRead() 
{ 
    Excel.Application excelApp = new Excel.Application(); 
    Workbook excelWorkbook = excelApp.Workbooks.Add(Type.Missing); 
    Worksheet worksheet = excelWorkbook.Sheets[1]; //1-based index 

    Guid rowGuid1 = Guid.NewGuid(); 
    const string filename = "C:\\temp\\anyTemporaryFilename.xlsx"; 

    //Make sure, this file does not exist previously 
    if (File.Exists(filename)) 
     File.Delete(filename); 

    //Write the ID to the worksheet 
    ((Range)worksheet.Cells[1, 1]).ID = rowGuid1.ToString(); 

    //Act (save and close the workbook) 
    excelWorkbook.SaveAs(filename); 
    excelWorkbook.Close(); 

    //Now open the workbook again 
    Workbook openedWorkbook = excelApp.Workbooks.Open(filename); 
    //Fetch the worksheet, where we worked previously 
    Worksheet openedWorksheet = openedWorkbook.Sheets[1]; //1-based index 

    //Read the ID from the cell 
    string guid1 = ((Range)openedWorksheet.Cells[1, 1]).ID; 

    //Cleanup 
    openedWorkbook.Close(false); 
    File.Delete(filename); 
    excelWorkbook.Close(false, Type.Missing, Type.Missing); 
    excelApp.Quit(); 

    //Assert - this fails!! 
    Assert.AreEqual(rowGuid1.ToString(), guid1); 

} 

私はエクセル-Worksheet-にIDを入れてどのように任意のアイデアを、感謝しますワークシートなどを保存するときに保持されるセル。

事前に多くのおかげで、 アレックス

アップデート2011年5月14日:

名フィールドには、次のような理由のために私の問題への解決策ではないように思わ:

まず、最も深刻なのは、名前が一意でなければならないという事実ですが、行内のすべてのセルに同じIDを与えたいと思っています。これはうまくいきません。

第2に、Cの名前フィールドにアクセスするには、私には本当に明確ではありません。

((Range)worksheet.Cells[rowNr, columnNr]).Name = guid.ToString(); 
//Remark: Special dealing with guids required, 
//if they start with a number or contain special characters. 

で値を設定できますが、重大な問題があります。名前が既に設定されている場合は、名前が設定されていない場合に例外がスローされ、アクセスしようとします。

string name = ((Range)worksheet.Cells[rowNr, columnNr]).Name.Name; 

例外があります。最初のName-fieldは文字列ではなく、文字列を含む別のName-Fieldを持つName-Object全体であるため、Name.Nameが必要です。

そして、あなたはそれが名前を持っているかいないかどうかを確認したい場合は、最終的に、あなたが行うことができない何かのように:

if(((Range)worksheet.Cells[rowNr, columnNr]).Name == null) 
    //Do something 

存在しない名前フィールドにアクセスするとき、それはすでに例外がスローされますので。

答えて

1

実際には、シートにIDをそのまま保持する方法はありません。 IDフィールド(永続化されていない)、名前(一意の名前のみが許可されているもの)、コメント(ユーザーに表示されているもの)のいずれにもなりません。

しかし、文字列を保持できるブック内にCustomPropertiesの概念があり、シリアル化可能なクラスをすべて文字列にマーシャリングできるため、プログラマーはIDを個別に保持し、ブックのロード時に復元できます。

私の目的のために、各行のハッシュ値を計算し、その代わりに行ハッシュ値を比較する別のアプローチが使用されました。

1

各セルに名前付き範囲を使用できます。名前は変わらない。私はinteropでこれを試していないが、それは良い古いvbaで動作します。以下のコードでは、名前をユーザーから隠すことができることに注意してください。私は、ブック内の名前付き範囲の数には論理limitありません理解して何から

Function try() 
    Dim x As Integer 
    Dim y As String 

    Worksheets("Sheet1").Range("a1").Name = "_firstCell" 
    Range("_firstCell").Value = 9999 
    Dim nm As Name 
    'hide 
    For Each nm In ActiveWorkbook.Names 
     If Left(nm.Name, 1) = "_" Then 
      nm.Visible = False 
     End If 
    Next 
    'move the named cell 
    Range("_firstCell").Cut Range("b1") 
    'check the value and address 
    x = Range("_firstCell").Value 
    y = Range("_firstCell").Address 

End Function 

0

は、使用してみてください:FormatConditions activecell.FormatConditions.Add xlExpression、formula1:= "test_1234" ID IDRange =ミッド(activecell.FormatConditionsは、(1).formula1,2) "test_1234"

の値を取得します
関連する問題