2015-11-13 93 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