2015-11-13 73 views
0

我有N個在存儲每天員工的活動在一個月的目錄Excel文件。他們有三列:日期,活動和類別。我不需要這個類別。有效的數據結構來保存員工的活動?

我想基本上看了N Excel文件和輸出,有效地使每個僱員按日期排序的所有活動,例如Word文檔:1

日至5日:

天:
僱員#1:
-task一個
-task b
-taskç

僱員#2:
-task一個
-task b
-taskç
...

第2天: ...
...
... 7
天至11天:
... ...

我想知道什麼數據結構我可以用來有效地持有這些信息,所以我可以很容易地寫我想要的文件。現在,我使用一個字符串數組來保存每個擅長行,他們都存儲在一個列表,然後在我的字典存儲每個員工,關鍵是每個員工的用戶名。

雖然我認爲這些數據結構是有效的自己,他們是不是我的主要目的是要打印每天下令對每個員工的數據太友好,所以也許關鍵本身應該是日期。

要回顧一下:當前數據結構使用:

Dictionary<string,List<string[]>> dictActividades = new  Dictionary<string,List<string[]>>(); 

在每個員工的Excel文件中所有的線都存儲在列表中。 我真的不需要字典功能,因爲我可以按順序閱讀所有內容。我可以馬上打印我正在讀一員工的Excel文件,但我將不得不看了N一次Excel文件(雖然n是很小的)

的思考?

編輯:這是我目前有:

 string directorioActividades = @"\\mar-fp01\mar_tecnologia$\Coordinacion de Apoyo a Usuarios\Informes\" + 
      fechaInicio.Year.ToString() + "\\" + fechaInicio.Year.ToString() + "-" + 
      fechaInicio.Month.ToString().PadLeft(2, '0'); 

     string[] archivos = Directory.GetFiles(directorioActividades, "*.xlsx"); 
     Dictionary<string,List<string[]>> dictActividades = new Dictionary<string,List<string[]>>(); 
     for (int j = 0; j < archivos.Length; j++) 
     { 
      List<string[]> actividades = new List<string[]>(); 
      string nombreArchivo = Path.GetFileNameWithoutExtension(archivos[j]); 
      String excelConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;" + 
       "Data Source=" + archivos[j] + ";" + 
       "Extended Properties=Excel 8.0; "; 
      using (OleDbConnection con = new OleDbConnection(excelConnectionString)) 
      { 
       OleDbCommand command = new OleDbCommand("Select * From [Actividades$]", con); 
       con.Open(); 

       OleDbDataReader dr = command.ExecuteReader(); 
       int cantidadcolumnas = dr.FieldCount; 

       string tipodatos = null; 
       string[] filaDatos = new string[cantidadcolumnas]; 
       while (dr.Read()) 
       { 
        for (int k = 0; k < cantidadcolumnas; k++) 
        { 
         tipodatos = dr.GetFieldType(k).ToString(); 
         if (tipodatos == "System.Int32") 
         { 
          filaDatos[k] = dr.GetInt32(k).ToString(); 
         } 
         if (tipodatos == "System.String") 
         { 
          filaDatos[k] = dr.GetString(k); 
         } 
         if (tipodatos == "System.DateTime") 
         { 
          filaDatos[k] = dr.GetDateTime(k).ToShortDateString(); 
         } 
        } 
        actividades.Add(filaDatos); 
       }//while dr.read 
      } 
      dictActividades.Add(nombreArchivo, actividades); 
     }//for archivos 

儘管此代碼是很短的,使用最少的數據結構,我能想到的,印刷是相當困難的,因爲關鍵是員工的用戶名,而不是日期和代碼應按日期列出的格式按日期列印每個員工的每項活動

回答

2

我會建議一個簡單的類像這樣

class EmployeeActivity 
{ 
    public string Employee { get; set; } 
    public DateTime Date { get; set; } 
    public string Activity { get; set; } 
} 

一個沒有特殊數據結構 - 只是List<EmployeeActivity>。一旦填充,您可以使用LINQ執行所需的排序/分組。

想象一下,而不是你字典您填充什麼我建議

var empoyeeActivies = new List<EmployeeActivity>(); 
// Iterate excel files like in your code and populate the list 

現在你可以用

var result = employeeActivities 
    .GroupBy(a => a.Date, (date, dateActivities) => new 
    { 
     Date = date, 
     DateActivities = dateActivities 
      .GroupBy(a => a.EmployeeName, (employeeName, employeeActivities) => new 
      { 
       EmployeeName = employeeName, 
       Activities = empoyeeActivities.OrderBy(a => a.Activity) 
      }) 
      .OrderBy(a => a.EmployeeName) 
    })  
    .OrderBy(a => a.Date); 
+0

這個類只能存儲excel的行,我基本上已經在一個字符串[3](我不需要存儲日期作爲日期,因爲我不計算任何相關日期)。我將用我目前的實施更新我的問題,以澄清 – fjleon

+0

如您所願。我的觀點是,你的excel文件結構不包含你所需要的任何數據,因此不需要特殊的數據結構 - 只是一個帶有值的扁平列表。 –

+0

@fjleon更新只是證明了我的觀點。首先,強類型比數組更好(這也是一個FYI類)。其次,無論你是否計算某些東西,日期最好存儲爲日期,而不是字符串。這有助於排序,分組等。而且這些報告很容易用LINQ查詢產生 - 事實上,這是LINQ專爲此設計的,而不是用普通代碼可以完成的奇特事情。 –

2

如果您不按語義組織它並且將邏輯包含在該數據中,則對此數據執行邏輯將非常不直觀楷模。考慮引用:

「智能數據結構和啞代碼比其他方式工作得更好。「
- 雷蒙德,大教堂和

你描述的結構包含了所有你需要的信息集市:一個

日:
員工#1:
-task一個
-task b
-taskç

所以,你開始一個Task對象:

class Task 
{ 
    // fields which describe a Task 
} 

(您可能需要將其命名東西略有不同,以避免混淆內置Task類型。 ?也許JobJobTask或類似的東西)

員工有任務的集合:

class Employee 
{ 
    public IList<Task> Tasks { get; set; } 
} 

,每天都有員工的集合:

class Day 
{ 
    public IList<Employee> Employees { get; set; } 
} 

(如果這個域名擴展除了這一個操作之外,你甚至可以命名一些不同的東西,從技術上講,這些是「員工」,比如他們是「EmployeeTaskLogs」,例如域的大小和複雜性將指導任何這樣的命名。想成爲最明智的名字,這是這項工作的整點)

那麼你的頂級消費代碼只在幾天的集合:

var days = new List<Day>(); 

您可以進一步完善了業務邏輯創建自定義集合類型。例如,如果你想利用天的詞典的優勢:

class DayDictionary<T> : IDictionary<T> where T : Day 
{ 
    // implement IDictionary<T> here 
} 

在這裏,你會包括對於像確保任何給定的集合剛好有5天的對象,例如邏輯。

一旦你定義了你的模型結構,使用它們變得微不足道,它們的語義變得明顯。

+0

變換而你的例子所示的方式,而我理解你的答案的基礎(謝謝!),我的感覺是,這對我想要做的事情有點複雜。請記住,我的數據輸入是excel文件,每個員工一個,每個人都有行,包含日期,活動和類別的描述(我不需要)。我已經有了可以打印週刊和週日的邏輯集,唯一缺少的就是每天以高效的方式打印所有員工的活動 – fjleon

+0

@fjleon:那麼也許您的頂級模型是Employee,每個人都有包含活動列表的天數列表。以任何有意義的方式將結構化爲正在建模的域。但是一旦你有了這個結構,查詢它變得非常簡單。例如,如果您有一個包含Days屬性的Employee對象列表,並且想要獲取給定Day的所有活動:'employees.SelectMany(e => e.Days).Where(d => d.Day = someDateValue )'或者如果您還需要Employee數據,則手動循環在Employees列表並單獨查詢Days集合。 – David