这是我在这里的第一篇文章,一般来说 - 我对 C# 很陌生,所以请原谅我的任何错误。我正在尝试执行以下操作:
- 1. 我有一个带有 3 张 excel 表的 excel 文件:sheet1, sheet2, sheet3。
- 2. 在每张 excel 表格中,我都有一个包含 3 列的表格:ID、名称、NEW_ID。所有这 3 列都是字符串类型,因此数组也可以工作。
- 3. 在我的代码开始时,我只想访问这个 excel 文件一次,并将这些工作表作为3 个单独的数组或列表输出到代码中,并让它们在代码执行结束时可用。
- 4. 我想将该数据填充到数组/列表中,因为稍后我必须在这些数组中搜索给定的 ID(列 ID)并从列 Name 和 NEW_ID 返回相应的值。我将不得不为大约 100k 个 ID 执行此操作,因此我不想每次都访问该文件,因为我相信它会减慢整个过程。
- 5. 我知道如何使用 OLEDB 从 excel 访问数据,因为我在这里检查了其他主题,但我不知道如何将该数据输出到 3 个单独的数组/列表并在这些数组/列表中搜索给定 ID 并返回相应的数组项。
感谢您的任何帮助!
这是我正在运行的代码。有问题的部分是代码末尾的ReadExcel类:
public class RecursiveFileProcessor
{
static void Main()
{
string InputMainFolder = "C:\\US\\";
string OutputMainFolder = "C:\\BAJ\\";
foreach (string InputFile in GetFiles(InputMainFolder))
{
Console.WriteLine(InputFile);
string InputPath = Path.GetDirectoryName(InputFile);
string InputFileName = Path.GetFileName(InputFile);
string OuputPath = InputPath.Replace(InputMainFolder, OutputMainFolder);
string OutputFile = System.IO.Path.Combine(OuputPath, InputFileName);
// To copy a folder's contents to a new location:
// Create a new target folder, if necessary.
if (!System.IO.Directory.Exists(OuputPath))
{
System.IO.Directory.CreateDirectory(OuputPath);
//Console.WriteLine("Ouput folder " + OuputPath + "created.");
}
// To copy a file to another location and
// overwrite the destination file if it already exists.
if (File.Exists(OutputFile))
{
Console.WriteLine("ERROR: File Already Exists: " + OutputFile);
continue;
}
else
{
System.IO.File.Copy(InputFile, OutputFile, true);
}
//Try to catch an exception
try
{
//Here comes some important part of my code (that works fine)
}
catch (Exception exe)
{
//call LogFile method and pass argument as Exception message, event name, control name, error line number, current form name
LogFile(exe.Message, exe.ToString(), exe.LineNumber(), InputFile, OutputMainFolder);
}
}
//call excel reader for tests
//THIS IS THE PLACE WHERE I WILL CALL MY EXCEL READER TO GET DATA INTO ARRAY/LIST/DATASET ETC
{
string MappingFile = "c:\\attributes mapping\\attributes mapping.xlsx";
ReadExcel.ReadExcelToTable(MappingFile);
}
//That's the final line of the code
Console.WriteLine("DONE: " + DateTime.Now.ToUniversalTime() + " UTC");
Console.ReadLine();
}
static IEnumerable<string> GetFiles(string path)
{
Queue<string> queue = new Queue<string>();
queue.Enqueue(path);
while (queue.Count > 0)
{
path = queue.Dequeue();
try
{
foreach (string subDir in Directory.GetDirectories(path))
{
queue.Enqueue(subDir);
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
}
string[] files = null;
try
{
files = Directory.GetFiles(path);
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
}
if (files != null)
{
for (int i = 0; i < files.Length; i++)
{
yield return files[i];
}
}
}
}
//This function writes exception details to the file in the output folder
public static void LogFile(string sExceptionName, string sEventName, int nErrorLineNo, string sFileName, string sOutputFolder)
{
StreamWriter log;
if (!File.Exists(sOutputFolder + "logfile.txt"))
{
log = new StreamWriter(sOutputFolder + "logfile.txt");
}
else
{
log = File.AppendText(sOutputFolder + "logfile.txt");
}
// Write to the file:
log.WriteLine("File Name:" + sFileName);
log.WriteLine("Data Time:" + DateTime.Now);
log.WriteLine("Error Line No.:" + nErrorLineNo);
log.WriteLine("Exception Name:" + sExceptionName);
log.WriteLine("Event Name:" + sEventName);
log.WriteLine("--------------------------------------------------------------------------");
// Close the stream:
log.Close();
}
}
//This part of code gets a line number where the exception appeared
public static class ExceptionHelper
{
public static int LineNumber(this Exception e)
{
int linenum = 0;
try
{
linenum = Convert.ToInt32(e.StackTrace.Substring(e.StackTrace.LastIndexOf(":line") + 5));
}
catch
{
//Stack trace is not available!
}
return linenum;
}
}
好的,我已经设法将这些数据放入 DataTables 中:
//Reads excel file and creates data sets from each excel sheet
public static DataSet ReadExcelToTable(string FileName)
{
//string HDR = hasHeaders ? "Yes" : "No";
string strConn;
if (FileName.Substring(FileName.LastIndexOf('.')).ToLower() == ".xlsx")
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + FileName + ";Extended Properties=\'Excel 8.0;HDR=YES;IMEX=1';";
else
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + FileName + ";Extended Properties=\'Excel 8.0;HDR=YES;IMEX=1';";
DataSet output = new DataSet();
using (OleDbConnection conn = new OleDbConnection(strConn))
{
conn.Open();
DataTable schemaTable = conn.GetOleDbSchemaTable(
OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
foreach (DataRow schemaRow in schemaTable.Rows)
{
string sheet = schemaRow["TABLE_NAME"].ToString();
if (!sheet.EndsWith("_"))
{
try
{
OleDbCommand cmd = new OleDbCommand("SELECT * FROM [" + sheet + "]", conn);
cmd.CommandType = CommandType.Text;
DataTable outputTable = new DataTable(sheet);
output.Tables.Add(outputTable);
new OleDbDataAdapter(cmd).Fill(outputTable);
}
catch (Exception ex)
{
throw new Exception(ex.Message + string.Format("Sheet:{0}.File:F{1}", sheet, FileName), ex);
}
}
}
}
return output;
这些数据表 (3) 必须在代码执行结束时可用。
ExcelReader 将返回 3 个 DataTables 作为输出,对吗?然后我必须在调用 ExcelReader 类并将这 3 个 DataTables 作为输出的地方之后继续编写代码。
现在我必须做这样的事情:
- 1. 假设“InputPath”字符串是这样的:
- C:\BAJ\Sheet1\ABCD或C:\BAJ\Sheet2\EFGH或C:\BAJ\Sheet3\IJKL(这些是随机名称)
- 2.如果“InputPath”包含“Sheet1”-->打开DataTable“Sheet1”
- 3.检查DataTable“Sheet1”中是否可以在ID列中找到ID=ABCD(也取自“InputPath”变量)
- 4. 如果找到 - 将对应的 NAME 和 NEW_ID 值作为变量返回,比如说:sName 和 sNew_Id
额外信息: ID 列中的 ID 是唯一的字符串,只能返回一个 Name 和一个 New_Id(也可以是字符串)。
有任何想法吗?