2009-07-03 5 views
2

Ich versuche C# zu erhalten, welche Arbeitsmappe der Benutzer ausgewählt hat, und alle Blätter zu finden, die Stock Daten enthalten würden. Konkret würde dies bedeuten, einen Bereich von Zellen zu betrachten (beispielsweise r < 6, c < 10) für "Schließen", "Schließen" oder "SCHLIESSEN".Durchsuchen einer Sammlung von Excel-Blättern w/C#

Der folgende Code zeigt den Punkt, an dem der Benutzer eine .xls-Datei ausgewählt hat.

Ich bin nicht sicher, wie Sie die Blätter in der Arbeitsmappe durchlaufen, um nach dem gewünschten Text zu suchen.

Ich nehme an, es beinhaltet eine Sammlung von Blättern zu schaffen und es den in der aktuellen Arbeitsmappe zuordnen, aber meine Versuche bisher nicht funktionierte.

private void button1_Click(object sender, System.EventArgs e) 
{ 
    try 
    { 
    OpenFileDialog dlg = new OpenFileDialog(); 
    dlg.Filter = "Excel Files (*.xls)|*.XLS"; 

    if (dlg.ShowDialog() == DialogResult.OK) 
    { 

     // MessageBox.Show(dlg.FileName, "My Application", MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk); 
     Excel.Application xlApp = new Excel.ApplicationClass(); 
     xlApp.Visible = true; 
     Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(dlg.FileName, 
       0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", 
       true, false, 0, true, false, false); 

    } 

    } 
    catch (Exception theException) 
    { 
    String errorMessage; 
    errorMessage = "Error: "; 
    errorMessage = String.Concat(errorMessage, theException.Message); 
    errorMessage = String.Concat(errorMessage, " Line: "); 
    errorMessage = String.Concat(errorMessage, theException.Source); 

    MessageBox.Show(errorMessage, "Error"); 
    } 
} 

Danke für jede Idee.

Jeff

Antwort

2

Bei der Verwendung der Interop-Bibliotheken müssen Sie immer vorsichtig vorgehen. Andernfalls werden wahrscheinlich einige Dutzend EXCEL.EXE-Prozesse im Hintergrund ausgeführt, während Sie debuggen (oder wenn ein Benutzer einen Fehler feststellt).

private static bool IsStockDataWorkbook(string fileName) 
{ 
    Excel.Application application = null; 
    Excel.Workbook workbook = null; 
    try 
    { 
     application = new Excel.ApplicationClass(); 
     application.Visible = true; 
     workbook = application.Workbooks.Open(fileName, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value); 

     foreach (Excel.Worksheet sheet in workbook.Worksheets) 
     { 
      if (IsStockWorksheet(sheet)) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 
    finally 
    { 
     if (workbook != null) 
     { 
      workbook.Close(false, Missing.Value, Missing.Value); 
     } 
     if (application != null) 
     { 
      application.Quit(); 
     } 
    } 
} 
private static bool IsStockWorksheet(Excel.Worksheet workSheet) 
{ 
    Excel.Range testRange = workSheet.get_Range("C10", Missing.Value); 
    string value = testRange.get_Value(Missing.Value).ToString(); 

    return value.Equals("close", StringComparison.InvariantCultureIgnoreCase); 
} 
+0

All diese "Missing.Value" s sind, warum Menschen VB.NET für Office Interop bevorzugen, und warum C# 4 das dynamische Keyword hat. –

+0

Ja, es ist wahr, dass Sie aufräumen müssen; Ich habe das in meiner schlampigen Antwort unten nicht erwähnt. Mein Verständnis ist, dass Marshal.FinalReleaseComObject (Objekt) für jede Variable aufgerufen werden sollte, die einem COM-Objekt zugewiesen ist. Ich denke, das bedeutet auch, dass Sie keine foreach-Schleife verwenden können, wie hier gezeigt. – Jay

+0

Crikey. Und das "application.Workbooks.Open()" verursacht Fehler. Just looked lesen durch http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c/159419 –

0
Workbooks workbooks = xlApp.Workbooks; 
foreach(Workbook wb in workbooks) 
{ 
    Worksheets worksheets = wb.Worksheets; 
    foreach(Worksheet ws in worksheets) 
    { 
     Range range = ws.get_Range(ws.Cells[1,1], ws.Cells[5,9]); 
     Range match = range.Find("close", ws.Cells[1,1], 
      xlFindLookIn.xlValues, xlLookAt.xlPart, 
      xlSearchOrder.xlByColumns, xlSearchDirection.xlNext, 
      false, false, false); //that first false means ignore case 
     // do something with your match here 
     // this will only return the first match; to return all 
     // you'll need to run the match in a while loop 
    } 
} 
+0

Danke, Jay. Mein Problem scheint darin zu liegen, dass die Sammlung von Arbeitsblättern richtig funktioniert. Aus irgendeinem Grund wird es auf der foreach-Anweisung aufgehängt. Alles, was ich versucht habe, erscheint rot. Fehle ich vielleicht einen Namensraum oder eine Referenz? Ich werde das weiter beobachten. Danke, Jeff –

2

Sie werden objSheets etwas zuweisen müssen, am wahrscheinlichsten:

Excel.Sheets objSheets = xlWorkbook.Sheets; 

Ihre foreach Aussage eher wie dieses aussehen sollte (ohne vorherige Erklärung deswsVariable):

foreach(Excel.Worksheet ws in objSheets) 
{ 
    rng = ws.get_Range(ws.Cells[1,1], ws.Cells[5,9]); 
} 

Offensichtlich werden Sie in dieser Schleife etwas Wesentlicheres tun wollen.

Verwandte Themen