我正在使某些工作自动化,因此我决定将其包含在SSIS包中。我已经为此工作了几个月,而我刚开始遇到的问题之一浮出水面。
我通过电子邮件收到一份报告,该报告已重命名下载并放入L:\ MACROS \ SSIS \ Input (这是通过我创建的C#应用程序完成的。)
然后我将数据从该报告导入SQL。
这里存在问题,因为我尝试从xls文件中获取数据,所以特定列具有2种行为中的1种。如果数据的第一行仅是数字,它将自动将其分配为数字,并且仅导入数字值,所有非数字都将转换为null。
此列是发票编号,通常是数字,但是在世界范围内,它们将是非数字的(即:“ MAGI:1326564” 打开数据流对象时,我收到此错误消息:
标题:Microsoft Visual Studio
以下输出列的元数据与 输出列所使用的外部列的元数据 相关:
输出“ Excel Source输出”:“ F11”
是否要将输出列的元数据替换为 外部列的元数据?
--------------------------------按钮:
&是&否
我可以获取数字值或非数字值。
现在,由于我想要一个永久性修复程序,因此我想到了仅使用C#进行创建 一个单独的非数字列,并将其从原始列中删除。
这样,我就有一种可重用的方法来解决上述问题。
try
{
//Start Excel and get Application object.
oXL = new Microsoft.Office.Interop.Excel.Application();
oXL.Visible = false;
oWB = (Microsoft.Office.Interop.Excel._Workbook)(oXL.Workbooks.Open(@"L:\MACROS\SSIS\Input\A2_POST_ADVICE_FOR_DUTY_LINES.xls"));
oSheet = (Microsoft.Office.Interop.Excel._Worksheet)oWB.ActiveSheet;
/* int nInLastRow = oSheet.Cells.Find("*", System.Reflection.Missing.Value,
System.Reflection.Missing.Value, System.Reflection.Missing.Value, Microsoft.Office.Interop.Excel.XlSearchOrder.xlByRows, Microsoft.Office.Interop.Excel.XlSearchDirection.xlPrevious, false, System.Reflection.Missing.Value, System.Reflection.Missing.Value).Row;
*/
var j = 7;
var cellValue = (string)(oSheet.Cells[7, 11] as Microsoft.Office.Interop.Excel.Range).Value;
// while (j < 20)/*nInLastRow)*/
// {
i = 0;
foreach (char value in cellValue)
{
bool digit = char.IsDigit(value);
if (digit == true)
{
i = i + 1;
}
else { i = i + 0; }
}
if (i > 1)
{
oSheet.Cells[j, 22] = cellValue;
//oSheet.Cells[j, 11].Clear();
}
// Close the workbook, tell it to save and give the path.
// j = j + 1;
// }
oXL.DisplayAlerts = false;
oWB.SaveAs(@"L:\MACROS\SSIS\Input\A2_POST_ADVICE_FOR_DUTY_LINES.xls", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing);
oWB.Close();
// Now quit the application.
oXL.Quit();
// Call the garbage collector to collect and wait for finalizers to finish.
GC.Collect();
GC.WaitForPendingFinalizers();
// Release the COM objects that have been instantiated.
Marshal.FinalReleaseComObject(oWB);
Marshal.FinalReleaseComObject(oSheet);
// Marshal.FinalReleaseComObject(oRng);
Marshal.FinalReleaseComObject(oXL);
}
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");
}
在运行C#时,我不断收到错误消息
“无法将类型double转换为字符串。
代码在执行循环之前(两次尝试)有效,在执行循环之后不再起作用,因此我注释掉了循环,但仍然遇到相同的错误。
我也改变了:
var cellValue = (string)(oSheet.Cells[7, 11] as Microsoft.Office.Interop.Excel.Range).Value;
到
var cellValue = (oSheet.Cells[7, 11] as Microsoft.Office.Interop.Excel.Range).Value.ToString();
此更改可用于2个测试,并且不再可用。
如果我将其更改为:
string cellValue = "MA1352564";
它将执行我想要的操作,因此我将其范围缩小到试图将单元格的值转换为字符串以便可以在那里检查字符串中的字符是否为数字的问题。
我正在寻找导入问题的其他解决方案,或者关于如何解决代码的C#部分的任何想法:)
编辑:我忘了提一下,如果我在流中启用了数据查看器,则来自excel的数据已经被剥离了非数字数据。...
EDIT2:
使用建议的选项后,出现此错误:
错误:DataInputUni处的错误:0xC0202009,Excel源[12]:SSIS错误代码 DTS_E_OLEDBERROR。发生OLE DB错误。错误代码: 0x80040E21。 OLE DB记录可用。资料来源:“ Microsoft JET 数据库引擎”结果:0x80040E21说明:“多步OLE 数据库操作生成错误。检查每个OLE DB状态值,如果 可用。未完成任何工作。”。错误:DataInputUni处为0xC0208265, Excel Source [12]:无法检索列“ F11”的长数据。 错误:DataInputUni处为0xC020901C,Excel源[12]:存在一个 Excel Source.Outputs [Excel Source Output] .Columns [F11]上的错误 Excel Source.Outputs [Excel源输出]。返回的列状态 原为:“ DBSTATUS_UNAVAILABLE”。在DataInputUni,Excel上错误:0xC0209029 源[12]:SSIS错误代码DTS_E_INDUCEDTRANSFORMFAILUREONERROR。 “ Excel Source.Outputs [Excel源输出] .Columns [F11]”失败 因为发生错误代码0xC0209071,并且错误行的配置 在“ Excel Source.Outputs [Excel Source Output] .Columns [F11]”上指定 错误失败。指定的对象发生错误 指定的组件。在此之前可能会发布错误消息 有关失败的更多信息。错误:0xC0047038,位于 DataInputUni,SSIS.Pipeline:SSIS错误代码DTS_E_PRIMEOUTPUTFAILED。 Excel Source上的PrimeOutput方法返回错误代码0xC0209029。 当管道引擎调用时,组件返回失败代码 PrimeOutput()。故障代码的含义由 组件,但错误是致命的,并且管道停止执行。 在此之前可能会发布错误消息,并提供更多信息 关于失败。
答案 0 :(得分:1)
听起来好像Excel驱动程序在猜测数据类型时没有读取足够的数据。除了根据注释在连接字符串中设置;Extended Properties="IMEX=1"
之外,还要根据哪个版本的Office(可能位于以下项之一)将TypeGuessRows注册表项设置为0:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel\TypeGuessRows
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Jet\4.0\Engines\Excel\TypeGuessRows
HKEY_LOCAL_MACHINE\Software\Microsoft\Office\
办公数字版本 \Access Connectivity Engine\Engines\Excel\TypeGuessRows
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Office\
办公数字版本 \Access Connectivity Engine\Engines\Excel\TypeGuessRows
将TypeGuessRows设置为0会导致在猜测数据类型时扫描整个列。当遇到混合值时,设置IMEX = 1会导致数据以文本形式返回(可以在注册表中更改)。忽略IMEX = 1会使与猜测的数据类型不匹配的数据返回为null。因此,IMEX不如TypeGuessRows重要,因为设置IMEX仅当在前8行中遇到足够多的变化时才能产生合理的差异(默认扫描) ),以显示多样性
http://microsoft-ssis.blogspot.com/2011/06/mixed-data-types-in-excel-column.html
答案 1 :(得分:0)
感谢Caius Jard的回答。我找到了解决问题的方法,我尝试将报告的输出文件格式更改为CSV,但这使情况更糟。使用CSV时,它根本不会扫描所有单元格并将所有内容分配为字符串,这会导致导入问题。然后,我尝试使用.xlsx(2007 excel)表示新的连接管理器,并将其作为连接字符串:
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=L:\MACROS\SSIS\Input\A2_POST_TEST20190103214110525.xlsx;Extended Properties="EXCEL 12.0 XML;HDR=NO";
我没有再添加Caius的建议,而是尝试将其更改为:
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=L:\MACROS\SSIS\Input\A2_POST_TEST20190103214110525.xlsx;Extended Properties="EXCEL 12.0 XML;HDR=NO;IMEX=1";
这解决了我的问题!