2016-04-09 4 views
2

Ich bin sehr neu bei C# und habe einen ziemlich klobigen Code geschrieben. Ich habe viele Kurse online gemacht und viele sagen, dass es mehrere Möglichkeiten gibt, Probleme anzugehen. Jetzt habe ich ein Programm erstellt, das eine .Doc Word-Datei lädt und dann mit if-Anweisungen nach den relevanten Informationen sucht.Wie beschleunigt man Word-Interop-Verarbeitung?

Jetzt ist mein Problem mit meiner Lösung, dass dieses Programm für immer dauert !!! Ich spreche von 30 Minuten - 1 Stunde, um den folgenden Code zu vervollständigen.

Irgendwelche Ideen, wie ich mein kleines Programm etwas weniger klobig machen kann? Ich hoffe, dass die Lösungen dazu mein Wissen wesentlich erhöhen werden, also danke im Voraus jeder!

Grüße chris

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

namespace WindowsFormsApplication3 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 
     public int id = 0; 
     public int[] iD = new int[100]; 
     public string[] timeOn = new string[100]; 
     public string[] timeOff = new string[100]; 
     public string[] dutyNo = new string[100]; 
     public string[] day = new string[100]; 

     private void button1_Click(object sender, EventArgs e) 
     { 



      Microsoft.Office.Interop.Word.Application application = new Microsoft.Office.Interop.Word.Application(); 
      Microsoft.Office.Interop.Word.Document document = application.Documents.Open("c:\\Users\\Alien\\Desktop\\TESTJOBS.doc"); 
      //the following for will loop for all words 

      int count = document.Words.Count; 
      for (int i = 1; i <= count; i++) 
      { 
       // the following if statement will look for the first word that is On 
       // this is then (on the file) proceded by 04:00 (thus i+2/3/4 respectively) 
       if (document.Words[i].Text == "On") 
       { 
        iD[id] = id; 
        // Console.WriteLine("ID Number ={0}", iD[id]); 
        dutyNo[id] = document.Words[i - 14].Text; 
        // Console.WriteLine("duty No set to:{0}", dutyNo[id]); 
        timeOn[id] = document.Words[i + 2].Text + document.Words[i + 3].Text + document.Words[i + 4].Text; 
        // Console.WriteLine("on time set to:{0}", timeOn[id]); 
        // the following if (runs if the last word was not "On" and then searches for the word "Off" which procedes "On" in the file format) 
        // this is then (on the file) proceded by 04:00 (thus i+2/3/4 respectively) 
       } 
       else if (document.Words[i].Text == "Off") 
       { 
        timeOff[id] = document.Words[i + 2].Text + document.Words[i + 3].Text + document.Words[i + 4].Text; 
        //Console.WriteLine("off time set to:{0}", timeOff[id]); 
        // the following if (runs if the last word was not "Off" and then searches for the word "Duty" which procedes "Off" in the file format) 
        // this is then (on the file) proceded by 04:00 (thus i+2/3/4 respectively) 
       } 
       else if (document.Words[i].Text == "Days" && !(document.Words[i + 3].Text == "Type")) 
       { 

        day[id] = document.Words[i + 2].Text; 
        //Console.WriteLine("day set to:{0}", day[id]); 
        //we then print the whole new duty out to ListBox1 
        listBox1.Items.Add(string.Format("new duty ID:{0} Time on:{1} Time off:{2} Duty No:{3} Day:{4}", iD[id], timeOn[id], timeOff[id], dutyNo[id], day[id])); 
        id++; 
       } 


      } 

      for (int i = 1; i <= 99; i++) 
      { 
       Console.WriteLine("new duty ID:{0} Time on:{1} Time off:{2} Duty No:{3} Day:{4}", iD[id], timeOn[id], timeOff[id], dutyNo[id], day[id]); 
      } 


     } 
    } 
} 
+1

Das ist, was passiert, wenn man offen docs von Aliens ... (_ "Open (" c: \\ Users \ \ Alien \\ Desktop \\ TESTJOBS.doc "_) –

+0

haha ​​sie strahlten sie einfach auf mich runter! –

+1

Haben Sie Timing-Diagnose (Stoppuhr-Klasse) in den Code zu sehen, was die Zeit nimmt? – ChrisF

Antwort

2

Office-Interop ist fairly slow.

Openxml möglicherweise , aber die Datei ist DOC, so wird es wahrscheinlich nicht in der Lage, damit umzugehen.


Aber genau wie mit Excel in this question gibt es eine Art und Weise Sie die Leistung verbessern können - greifen nicht jedes Wort in einem Range von Index, weil AFAIK in RCW wickelte es Schaffung einer eigenen Range Instanz verursacht , und das ist der primäre Kandidat für einen Leistungsengpass in Ihrer Anwendung.

Das bedeutet, dass die beste Wahl, die Leistung zu verbessern, ist zu Last all Worte (.Text) in eine Wende Sammlung von String s vor der eigentlichen Verarbeitung, und nur dann diese Sammlung verwenden, um die Ausgabe zu erstellen.

Wie geht das am schnellsten? Ich bin nicht ganz sicher, aber Sie können versuchen, entweder alle Wörter von enumerator (obwohl es möglicherweise leistungsfähiger oder nicht sein kann, aber zumindest werden Sie in der Lage zu sehen, wie lange es dauert, um nur die erforderlichen Wörter abrufen):

var words = document 
    .Cast<Range>() 
    .Select(r => 
     r.Text) 
    .ToList(); 

oder Sie können versuchen, _Document.Content Bereich Text verwenden, obwohl würden Sie dann einzelne Wörter selbst trennen müssen.

+0

Danke Eugene Ich werde morgen an diesen Änderungen arbeiten. –

0

Statt mit:

document.Words[i].Text 

mehrere Male tun:

String Text = document.Words[i].Text; 

an der Spitze der for-Schleife und verwenden "Text" (oder was auch immer Sie es nennen wollen) statt. Eugene Podskals Vorschläge scheinen sehr hilfreich zu sein, aber diese einfache Verbesserung (an die ich dachte, bevor ich Eugens Antwort gesehen habe) ist sehr einfach zu machen und könnte eine wesentliche Verbesserung bewirken.

+0

Ich glaube nicht, dass dies funktionieren würde, da ich Words [i] verwende und innerhalb der If-Anweisungen selbst hoch und runter wechsle, um die spezifischen Positionen der erforderlichen Informationen zu finden. Korrigiere mich, wenn ich falsch liege! –

0

Ok Fertig damit wir nun alle Informationen wie vorher verarbeiten und das ganze Dokument trotzdem importieren. Gesamtlaufzeit ist 02: 09.8 für 2780 Sätze und ca. 44.000 Wörter (das beinhaltet Leerzeichen!) Unten ist mein (nicht perfekter Code) nicht schlecht, wenn ich C# vor 2 Wochen abgeholt habe;) Hoffe das hilft jemandem in der Zukunft.

public Form1() 
    { 
     InitializeComponent(); 
    } 
    public int id = 0; 
    public int[] iD = new int[400]; 
    public string[] timeOn = new string[400]; 
    public string[] timeOff = new string[400]; 
    public string[] dutyNo = new string[400]; 
    public string[] day = new string[400]; 
    public string[] hours = new string[400]; 

    //Create File Location Var 
    public string fileLocation = null; 

    // On Click of Add Dutys 
    private void button1_Click(object sender, EventArgs e) 
    { 
     //Sets Progress Bar visible and prepares to increment 
     pBar1.Visible = true; 
     pBar1.Minimum = 1; 
     pBar1.Value = 1; 
     pBar1.Step = 1; 


     //Stopwatch test Declared 
     Stopwatch stopWatch = new Stopwatch(); 

     try { 
      //Self Test to see if a File Location has been set for Duty document. 
      if (fileLocation == null) { 
       //If not set prompts user with message box and brings up file explorer 
       MessageBox.Show("It Appears that a file location has not yet been set, Please Select one now."); 
       Stream myStream = null; 
       OpenFileDialog openFileDialog1 = new OpenFileDialog(); 
       //Sets default Location and Default File type as .doc 
       openFileDialog1.InitialDirectory = "c:\\"; 
       openFileDialog1.Filter = "All files (*.*)|*.*|Word Files (*.doc)|*.doc"; 
       openFileDialog1.FilterIndex = 2; 
       openFileDialog1.RestoreDirectory = true; 
       //Waits for User to Click ok in File explorer and then Sets file location to var 
       if (openFileDialog1.ShowDialog() == DialogResult.OK) 
       { 
        try 
        { 
         //Checks to make sure a file location is set 
         if ((myStream = openFileDialog1.OpenFile()) != null) 
         { 
          using (myStream) 
          { 
           //This is where we set location to var 
           fileLocation = openFileDialog1.FileName; 
          } 
          //Prompts user to click a file before OK 
         }else { MessageBox.Show("Please Select a file location before clicking ok"); } 
        } 
        catch (Exception ex) 
        { 
         MessageBox.Show("Error: Could not read file from disk: " + ex.Message); 
        } 
       } 
      } 

      //Loads New Duty file 
      Microsoft.Office.Interop.Word.Application application = new Microsoft.Office.Interop.Word.Application(); 
      Microsoft.Office.Interop.Word.Document document = application.Documents.Open(fileLocation); 
      //Begin stop watch (COPY TIME) 
      stopWatch.Start(); 

      //Sets Count to No of sentences and then prepares Array using Number of sentences 
      //**This process reduces amount of processng time by taking everything in to the program to start and then dealing with it. 
      int count = document.Sentences.Count; 
      string[] sents = new string[count]; 
      //Then sets the Progress bar to the Number of sentences that will be Copied to our array 
      pBar1.Maximum = count; 

      try { 
       //For loop runs throug every sentence and adds it to the array. 
       for (int i = 0; i < count; i++) { 
        sents[i] = document.Sentences[i+1].Text; 
        //increment Progress bar by 1 for every sentence(Parse made) 
        pBar1.PerformStep(); 
       } 
       //Closes our instance of word 
       application.Quit(); 
       try { 

        for (int i = 0; i < count; i++) 
        { 
         //Sets our Split criteria 
         char[] delimiterChars = { ' ','\t' }; 
         string[] test = (sents[i].Split(delimiterChars)); 
         //we then enter For loop that runs for the number of ords found/Split 
         for (int a = 0; a < test.Length; a++) 
         { 
          //If tests only begin if the word is NOT a space blank, tab , - As these do parse through into our Test arrays 
          if (!(test[a] == "" || test[a].Contains("/t")|| test[a].Contains("-") || test[a].Contains(" "))) 
          { 
           //If tests to find Duty numbers ours on off and assigns ID number for easy indexing. 
           //##THIS DOES ASSUME THAT OUR TIMES ARE 1 SPACE AFTER THEIR IDENTIFIERS. 
           if (test[a] == "TG") 
           { 
            dutyNo[id] = test[a + 2]; 
           } 
           else if (test[a] == "On") 
           { 
            iD[id] = id; 
            timeOn[id] = test[a + 1]; 
           } 
           else if (test[a] == "Off") 
           { 
            timeOff[id] = test[a + 1]; 
           } 
           else if (test[a] == "Hrs") 
           { 
            hours[id] = test[a + 1]; 
           } 
           else if (test[a] == "Days") 
           { 
            day[id] = test[a + 1]; 
            //PRINTS TO USER VIA LIST BOX ALL THE DUTYS ADDED. 
            listBox1.Items.Add(string.Format("ADDED:Duty No:{3} Time on:{1} Time off:{2} Hours{5} Day:{4} ID:{0}", iD[id], timeOn[id], timeOff[id], dutyNo[id], day[id], hours[id])); 
            id++; 
           } 

          } 
         } 
        } 
       } 
       catch(Exception ex) { MessageBox.Show("Error in split:" + ex.Message); } 
      } 
      catch(Exception ex) { MessageBox.Show("error setting string to Document:" + ex.Message); } 
      //Stopwatch Is then printed for testing purposes. 
      TimeSpan ts = stopWatch.Elapsed; 
      string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, 
      ts.Milliseconds/10); 
      Console.WriteLine("RunTime (total):" + elapsedTime); 

      stopWatch.Reset(); 

     } 
     catch(Exception ex) { MessageBox.Show("Error in reading/finding file: "+ ex.Message); } 

    } 


} 

}

ich all diesen Code mit einem ziemlich großen Listenfeld (ListBox1) ein Button (Button1) und einem nicht sichtbar auf Start-up-Fortschrittsbalken (pBar1).

0

Sie können den gesamten .content Bereich mit OpenXml laden und verarbeiten wie, dass es, dann wieder importiert es

Verwandte Themen