3

SpreadsheetLightを使用して、WinForms プロジェクトからログ ファイルを書き込んでいます。Interop私の意図は、同じファイル内の 3 つのワークシートにログ エントリを書き込むことです。回避できる場合は 使用を避けたいと思っています。

行タイトルが事前に入力された 3 つのワークシートを含む Excel で作成されたテンプレート ファイルから始めます。各ワークシートには同じ基本プロパティ (個別に異なる可能性があります) があるため、各シートをクラスにカプセル化します。このような:

/// <summary>
/// Encapsulate the info we need to know about each worksheet in order to populate properly
/// </summary>
public class LogSheet
{
    public SLDocument data;
    public SLWorksheetStatistics stats;
    public int RowCount;
    public int ColumnCount;
    public int currentColumn;                             //indicates what column you want to be writing to
    public List<string> rowNames = new List<string>();    //used to make sure you're writing new data to the right row
    public List<string> columnNames = new List<string>(); //used by GetLatestRun() to check if data already exists for a given serial number

    public LogSheet(string sheet)
    {
        this.data = new SLDocument(_path, sheet);
        this.stats = this.data.GetWorksheetStatistics();
        this.RowCount = this.stats.EndRowIndex;
        this.ColumnCount = this.stats.EndColumnIndex;

        currentColumn = GetLatestRun();

        for (int i = 1; i < RowCount + 1; i++)
        {
            this.rowNames.Add(this.data.GetCellValueAsString(i, 1));
        }

        for (int i = 1; i < ColumnCount + 1; i++)
        {
            this.columnNames.Add(this.data.GetCellValueAsString(1, i));
        }
    }
}

LogSheetクラスには示されていませんが、適切な場所へのデータの書き込みを処理するメソッドもいくつかあります。

これはすべて正常に動作しているように見えます。デバッグ時に、インスタンス化された 3 つのワークシートのそれぞれにnew LogSheet(<sheetName>)、書き込み後に想定されるデータが含まれていることがわかります。

問題は、データを保存したいときに で回避できることですがthis.data.Save()、1 つのワークシートしか保存されず、Save()メソッドがターミナルで Excel ファイルを閉じるため、他の 2 つは宙に浮いたままになっています。もちろん、スプレッドシートを強制終了し、シートに参照するものがなくなったため、他の2つのシートのいずれかでメソッドを試すSave()と、例外が発生します。結果のファイルには、最初に保存したときのデータしかありません。"Object reference not set to an object"Save()

これを回避する方法についての私の最善の推測は、SLDocumentシートごとに新しいインスタンスを作成せず、代わりにSLDocument.SelectWorksheet()特定のワークシートに書き込みたいたびに使用することですが、それでも LogSheet クラスにカプセル化したままにしたいと考えています。まだ関連しています。

他の提案はありますか?

4

1 に答える 1

4

推奨される効率的な方法は、すべてのログを最初にメモリに格納することです (List<> などを使用)。次に、書き込み時に、ワークシートを選択し、最初の List<> からすべてを書き込み、2 番目のワークシートを選択し、2 番目の List<> からすべてを書き込み、3 番目のワークシートを選択し、3 番目の List<> からすべてを書き込みます。

メモリに問題がある場合は、最初のワークシートを選択し、ログ チャンクをセル値に書き込み、2 番目のワークシートを選択し、ログ チャンクをセル値に書き込みます (2 番目のワークシートが現在選択されているため、2 番目のワークシートになります)、3 番目のワークシートを選択し、ログ チャンクを書き込みます。次に、上記を使用してすべてのログ チャンクを反復処理します。

後者の方法では、一度に消費するメモリは少なくなりますが、ワークシート間を行き来するため、より多くの CPU サイクルが必要になります。行ったり来たりすることは、1 つのワークシートをロードしてアンロードし、別のワークシートをロードすることと同じです。

于 2015-05-04T08:14:27.503 に答える