簡體   English   中英

對於 SSIS Package 中的 SQL 服務器,如何將 XML 文件中的 Excel 序列號轉換為 mm/dd/yyyy?

[英]How do I convert Excel Serial Date Numbers in an XML file to mm/dd/yyyy for SQL Server in an SSIS Package?

我收到了一個 XML 文件,其中日期字段是 Excel 序列日期編號,而不是通常的 mm/dd/yyyy 日期。 我在向我先前存在的 SSIS package 添加數據轉換時遇到問題,因為序列號在 XML 文件中,而不是 excel 文件中。

SSIS package 清理並加載一個 883812976388 文件到 SQL 服務器表中。

有人有什么想法嗎? 我在 Visual Studios 2015 fyi 工作。

XML 數據片段:

    <AGREEMENT_CODE>1960-EMPR</AGREEMENT_CODE>
        <AGREEMENT_NAME>1960-Legacy Employer Conversion 
    Default</AGREEMENT_NAME>
        <AGREEMENT_TYPE>MBA</AGREEMENT_TYPE>
        <FUND_TYPE>Health &amp; Pension</FUND_TYPE>
        <CONTRACT_START_DATE>21916</CONTRACT_START_DATE>
        <EMPLOYER_ID>25568</EMPLOYER_ID>
        <EMPLOYER_NAME>10409</EMPLOYER_NAME>
        <BILLING_ENTITY_CODE>ACT III TELEVISION, L.P.</BILLING_ENTITY_CODE>
        <BILLING_ENTITY_NAME>10409</BILLING_ENTITY_NAME>
        <PARTICIPATION_START_DATE>ACT III TELEVISION, L.P. 
   </PARTICIPATION_START_DATE>
        <PARTICIPATION_SIGNED_DATE>35917</PARTICIPATION_SIGNED_DATE>

Excel 序列號位於第 6 行和第 13 行。它們是 5 位數字。

Excel 中的日期實際上是一個數字,代表(出於所有意圖和目的)自 1899 年 12 月 30 日以來的天數。但是下面有一個警告。

因此,您可以使用DATEADD(day, @yourDateNum, '18991230')將數字轉換為日期

需要注意的是,Microsoft(以及之前的 Lotus 1-2-3)在日期計算中存在錯誤: 他們假設 1900 年是閏年,但事實並非如此。 因此,還有額外的一天,我已經調整了上面的公式以考慮到這一點。 然而,結果是此公式不適用於 1900 年 3 月 1 日之前的日期。

請在投入生產前用已知值檢查您的公式!

我使用了十多年的代碼現在來自一個不存在的站點

    /// <summary>
    /// Seriously?  For the loss
    /// <see cref="http://www.debugging.com/bug/19252"></see>
    /// </summary>
    /// <param name="excelDate">Number of days since 1900-01-01</param>
    /// <returns>The converted days to date</returns>
    public static DateTime ConvertXlsdtToDateTime(int excelDate)
    {
        DateTime dt = new DateTime(1899, 12, 31);

        // adjust for 29 Feb 1900 which Excel considers a valid date
        if (excelDate >= 60)
        {
            excelDate--;
        }

        return dt.AddDays(excelDate);
    }

如果您要在派生列任務中使用它,則需要將 C# 轉換為 SSIS 表達式語言。 我們將使用三元運算符(boolean)? truevalue: falsevalue (boolean)? truevalue: falsevalue來實現這一點

DATEADD("Day", [CONTRACT_START_DATE] - ([CONTRACT_START_DATE] >= 60 ? 1 : 0), (DT_DATE)"1899-12-30")

通常,我的數據流中會有兩個派生列組件,因為這是調試事物的唯一方法。 在您的情況下,我會讓第一個派生列向數據流添加 1 + Number Of Excel 列。

請注意,此處顯示的賦值=是您在派生任務中放入Derived Column NameExpression列的值的簡寫語法

BaseDate = (DT_DATE)"1899-12-30"
CONTRACT_START_DATE_Offset = [CONTRACT_START_DATE] >= 60 ? -1 : 0
PARTICIPATION_SIGNED_DATE_Offset = [PARTICIPATION_SIGNED_DATE] >= 60 ? -1 : 0

等。現在我可以檢查我是否正確處理了 1900 錯誤的偏移值。

然后將我的第一個表達式簡化為

DATEADD("Day", [CONTRACT_START_DATE] - [CONTRACT_START_DATE_Offset], [BaseDate])

如果您真的想找出 go 可能出錯的地方,我什至會考慮將Col1 - Col1_Offset中的數學邏輯封裝到前體派生列中,這樣我就可以在其上放置數據抽頭/數據查看器並捕獲值.

作為最小復制,我創建了一個 package,它有一個 OLESRC 組件,將我們的 CONTRACT_START_DATE 添加到數據流中

SELECT 35 AS CONTRACT_START_DATE
UNION ALL SELECT 21916

使用第一個表達式的我的派生列“OneShot”添加列“OneShot”

DER Multistatement 添加第二組表達式中的 BaseDate 和 CONTRACT_START_DATE_Offset 值

DER CSD 使用第三個表達式將 ContractStartDate 添加到數據流中。

在此處輸入圖像描述

在上圖中,您可以看到數據查看器的結果(以及此時的元數據副本)。 使用 DATEADD function - DT_DBTIMESTAMP 后,我的數據類型符合預期。

如果您的類型顯示為 DT_WSTR,請確保您正在添加新列而不是嘗試替換現有列。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM