2009-01-23 108 views
2

我的任務是爲我們的財務部門創建可重複使用的流程,將我們的工資單上傳到州(威斯康星州)進行報告。我需要創建一些在Excel中使用表格或範圍並創建特定格式的文本文件。將Excel範圍/工作表導出爲格式化文本文件

THE FORMAT

  • 列1 - 的靜態編號,從不改變,位置1-10
  • 列2 - 動態帕拉姆填充在運行時爲四分之一/年,11-位置13
  • 柱3 - SSN,沒有連字符或空格, 從柱的填充,位置14-22
  • 柱4 - 姓,從 ç填充olumn B,在10截斷,左 對齊&填補空白,位置 23-32
  • 柱5 - 名字,從C, 截斷爲8,左填充對齊&填充 用空格,位置33-40 6
  • 柱 - 總工資總額/區,從 填充d,去除所有的格式, 右對齊零填充,位置 41-49
  • 柱7 - 一種靜態代碼,從未 變化,位置50-51
  • 第8欄 - 空格鍵,有填空, 位置52-80

我有,我想,3個選項:

  1. VBA
  2. .NET
  3. SQL

我已經探索了.NET方法,但我找不到像樣的文檔讓我走。我仍然喜歡這個,但我離題了。

接下來我有一些VBA將轉儲到固定寬度文本的工作表。我目前正在追求這一點,最終導致我的實際問題。

如何在Excel中轉​​換文本範圍?我是否需要將它粘貼到另一張紙上,然後使用neccesarry格式化函數將該數據傳遞給我的轉儲到文本例程?我目前已經計劃爲每列提供一個函數,但是我很難弄清楚如何進行下一步操作。我在Office編程和一般開發方面相當新,所以任何見解都將不勝感激。

SQL選項可能會倒退,因爲過去我從SQL執行過類似的導出操作。我只是比較喜歡其他兩個,「我不想負責運行這個」,原理。

在任何時間提前致謝。

+0

優秀的問題和答案。 – 2009-01-27 01:53:03

回答

4

使用VBA似乎是要走我的路。這可以讓你編寫一個處理所有各種格式化選項的宏,並且希望對於你的財務人員來說可以很簡單。

你說你需要一些在Excel中使用表格或範圍的東西。第一列從不改變,所以我們可以將其存儲在宏中,第3-7列來自電子表格,而第8列只是空白。這留下第2列(季度/年爲QYY)作爲一個問題。如果在工作簿中某處指定了季度/年份(例如存儲在單元格中,作爲工作表名稱,作爲工作簿標題的一部分),那麼我們可以將其讀入。否則,您需要找到一些方法來指定季度/年,當宏運行(例如彈出一個對話框,要求用戶輸入的話)

一些簡單的代碼(我們會擔心如何調用這個版本):

Sub ProduceStatePayrollReportFile(rngPayrollData As Range, strCompanyNo As String, _ 
    strQuarterYear As String, strRecordCode As String, strOutputFile As String) 

參數是相當明顯的:保存數據的範圍,列1的公司編號,列2的季度/年,列7的固定代碼和我們想要輸出結果的文件到

' Store the file handle for the output file 
Dim fnOutPayrollReport As Integer 
' Store each line of the output file 
Dim strPayrollReportLine As String 
' Use to work through each row in the range 
Dim indexRow As Integer 

要在VBA中輸出到文件,我們需要獲取文件句柄,因此我們需要一個變量來存儲它。我們將在報告行字符串中構建報告的每一行,並使用行索引在範圍內工作

' Store the raw SSN, last name, first name and wages data 
Dim strRawSSN As String 
Dim strRawLastName As String 
Dim strRawFirstName As String 
Dim strRawWages As String 
Dim currencyRawWages As Currency 

' Store the corrected SSN, last name, first name and wages data 
Dim strCleanSSN As String 
Dim strCleanLastName As String 
Dim strCleanFirstName As String 
Dim strCleanWages As String 

這些變量集分別存儲工作表的原始數據和要輸出到文件的清理數據。將它們命名爲「原始」和「乾淨」,可以更容易地發現意外輸出原始數據而非清理數據的錯誤。我們需要改變從一個字符串值的原始工資爲一個數值,以幫助格式化

' Open up the output file 
fnOutPayrollReport = FreeFile() 
Open strOutputFile For Output As #fnOutPayrollReport 

FreeFile()獲取下一個可用的文件句柄,我們用它來鏈接到文件

' Work through each row in the range 
For indexRow = 1 To rngPayrollData.Rows.Count 
    ' Reset the output report line to be empty 
    strPayrollReportLine = "" 
    ' Add the company number to the report line (assumption: already correctly formatted) 
    strPayrollReportLine = strPayrollReportLine & strCompanyNo 
    ' Add in the quarter/year (assumption: already correctly formatted) 
    strPayrollReportLine = strPayrollReportLine & strQuarterYear 

在我們遍歷各行的工作,我們開始通過清除輸出字符串,然後添加在值列​​1和2

' Get the raw SSN data, clean it and append to the report line 
strRawSSN = rngPayrollData.Cells(indexRow, 1) 
strCleanSSN = cleanFromRawSSN(strRawSSN) 
strPayrollReportLine = strPayrollReportLine & strCleanSSN 

.Cells(indexRow, 1)部分只是表示indexRow指定的行範圍中最左邊的一列。如果範圍在A列開始(這並不一定是這種情況),那麼這也就意味着A.我們需要寫cleanFromRawSSN功能以後自己

' Get the raw last and first names, clean them and append them 
strRawLastName = rngPayrollData.Cells(indexRow, 2) 
strCleanLastName = Format(Left$(strRawLastName, 10), "[email protected]@@@@@@@@@") 
strPayrollReportLine = strPayrollReportLine & strCleanLastName 

strRawFirstName = rngPayrollData.Cells(indexRow, 3) 
strCleanFirstName = Format(Left$(strRawFirstName, 8), "[email protected]@@@@@@@") 
strPayrollReportLine = strPayrollReportLine & strCleanFirstName 

Left$(string, length)截斷字符串指定的長度。該格式圖片[email protected]@@@@@@@@@格式的字符串作爲正好十個字符,左對齊(的!表示左對齊),並用空格填充

' Read in the wages data, convert to numeric data, lose the decimal, clean it and append it 
strRawWages = rngPayrollData.Cells(indexRow, 4) 
currencyRawWages = CCur(strRawWages) 
currencyRawWages = currencyRawWages * 100 
strCleanWages = Format(currencyRawWages, "000000000") 
strPayrollReportLine = strPayrollReportLine & strCleanWages 

我們將其轉換爲貨幣,使我們可以乘以100移動美分值在小數點左側。這使得使用Format來生成正確的值變得更容易。這不會產生超過1000萬美元工資的正確輸出,但這是用於報告的文件格式的限制。在以0的格式的圖片墊令人驚訝的是

' Append the fixed code for column 7 and the spaces for column 8 
strPayrollReportLine = strPayrollReportLine & strRecordCode 
strPayrollReportLine = strPayrollReportLine & CStr(String(29, " ")) 

' Output the line to the file 
Print #fnOutPayrollReport, strPayrollReportLine 

String(number, char)功能0產生變體,與指定的charnumber的序列。 CStr將Variant變成一個字符串。該Print #聲明輸出到文件,無需任何額外的格式

Next indexRow 

' Close the file 
Close #fnOutPayrollReport 

End Sub 

循環輪的範圍和重複下一行。當我們處理了所有行時,關閉文件並結束宏我們仍然需要兩件事:一個cleanFromRawSSN函數和一個用相關數據調用宏的方法。

Function cleanFromRawSSN(strRawSSN As String) As String 

' Used to index the raw SSN so we can process it one character at a time 
Dim indexRawChar As Integer 

' Set the return string to be empty 
cleanFromRawSSN = "" 

' Loop through the raw data and extract the correct characters 
For indexRawChar = 1 To Len(strRawSSN) 
    ' Check for hyphen 
    If (Mid$(strRawSSN, indexRawChar, 1) = "-") Then 
     ' do nothing 
    ' Check for space 
    ElseIf (Mid$(strRawSSN, indexRawChar, 1) = " ") Then 
     ' do nothing 
    Else 
     ' Output character 
     cleanFromRawSSN = cleanFromRawSSN & Mid$(strRawSSN, indexRawChar, 1) 
    End If 
Next indexRawChar 

' Check for correct length and return empty string if incorrect 
If (Len(cleanFromRawSSN) <> 9) Then 
    cleanFromRawSSN = "" 
End If 

End Function 

Len返回字符串和從stringMid$(string, start, length)返回length字符在start開始的長度。此功能可以改善,因爲它目前不檢查非數字數據

要調用宏:

Sub CallPayrollReport() 

ProduceStatePayrollReportFile Application.Selection, "1234560007", "109", "01", "C:\payroll109.txt" 

End Sub 

這是調用它的最簡單方法。範圍是用戶在活動工作簿中的活動工作表上選擇的任何值,其他值是硬編碼的。用戶應該選擇他們想輸出到文件的範圍,然後進入工具>宏>運行,然後選擇CallPayrollReport。爲此,宏需要成爲包含數據的工作簿的一部分,或者需要在用戶調用宏之前加載的不同工作簿中。

有人需要在每季度報告生成之前更改季度/年份的硬編碼值。如前所述,如果季度/年已經存儲在工作簿,然後某處這是更好的閱讀,在而不是硬編碼

希望是有道理的,是一些使用的

-1

根據您的文檔格式,我可能會建議導出到.csv並使用它。如果你需要的只是數字,這將是最簡單的方法。

+0

感謝您的回答。我相信我很困惑。你指的是什麼文件的「格式」?我試圖在我的文章中概述這一點。其次,通過將我的xls變成csv可以獲得什麼? 再次感謝! – 2009-01-23 20:06:29

0

從最簡單的角度思考這個問題,並且如果您熟悉SQL,在Access的上下文中,您可以使用Access作爲外部數據源附加到電子表格。它看起來像Access中的一張桌子,並從那裏開始工作。

0

哇!我不得不說,我被吹走了。你遠遠超出了我的期望,答案是我感到內疚,我只能投票給你一次,並且標記爲例外。我曾經希望能夠獲得最佳路徑和某些格式的指導。祝我生日快樂!

Format()和FreeFile()是特別新的有用信息。此外,爲了表明我正在嘗試,我的嘗試如下。我非常接近,因爲我只是在制定格式細節,但我相信我會用您的意見來修改它,因爲它似乎是更優雅的方法。

作爲最後的筆記。我通過Jeff Atwood的博客找到了這個地方,我對這個想法感到非常興奮。作爲一個獨立商店中缺乏經驗的新開發者,我一直希望有一個地方可以轉向指導。書籍和文章讓你明白,但沒有什麼等於某人完成了它或曾經在那裏的建議。到目前爲止,StackOverflow已經交付。

僅供參考,我在另一個非常受歡迎的代碼論壇上發佈了完全相同的問題,但尚未以任何方式收到單個回覆。

現在我嘗試:

模塊代碼


    Sub StateANSIIExport() 
    Dim Sizes As Variant 
    Dim arr As Variant 
    Dim aRow As Long, aCol As Long 
    Dim rowLimit As Integer, colLimit As Integer 
    Dim SpacesPerCell As Integer 
    Dim fso As Object 
    Dim ts As Object 
    Dim TheLine As String 
    Dim TestStr As String 

    arr = ActiveSheet.UsedRange 
    rowLimit = UBound(arr, 1) 
    'colLimit = UBound(arr, 2) 
    colLimit = 8 
    SpacesPerCell = 20  'Set export text "column" width here 

    Set fso = CreateObject("Scripting.FileSystemObject") 
    Set ts = fso.CreateTextFile(GetDesktopPath() & "EXCELTEXT.txt", True) 

    ' Loop thru the rows 
    For aRow = 1 To rowLimit 
     TheLine = Space(colLimit * SpacesPerCell)  ' your fixed-width output 
     ' Loop thru the columns 
     For aCol = 1 To colLimit 
      Select Case aCol 
       Case 1 ' Employer UI Account # 
        Mid(TheLine, aCol * SpacesPerCell - SpacesPerCell + 1, SpacesPerCell) = "6979430002" 
       Case 2 ' Reporting Period (QYY) 
        Mid(TheLine, aCol * SpacesPerCell - SpacesPerCell + 1, SpacesPerCell) = "109" 
       Case 3 ' SSN 
        Mid(TheLine, aCol * SpacesPerCell - SpacesPerCell + 1, SpacesPerCell) = Cells(aRow, "A") 
       Case 4 ' Last Name 
        Mid(TheLine, aCol * SpacesPerCell - SpacesPerCell + 1, SpacesPerCell) = Cells(aRow, "B") 
       Case 5 ' First Name 
        Mid(TheLine, aCol * SpacesPerCell - SpacesPerCell + 1, SpacesPerCell) = Cells(aRow, "C") 
       Case 6 ' Employee Quartly Gross Wages 
        Mid(TheLine, aCol * SpacesPerCell - SpacesPerCell + 1, SpacesPerCell) = Cells(aRow, "D") 
       Case 7 ' Record Code 
        Mid(TheLine, aCol * SpacesPerCell - SpacesPerCell + 1, SpacesPerCell) = "01" 
       Case 8 ' BLANK 
        Mid(TheLine, aCol * SpacesPerCell - SpacesPerCell + 1, SpacesPerCell) = "        " 
      End Select 
     Next aCol 
     ' Write the line to the file 
     ts.WriteLine TheLine 
    Next aRow 

    ts.Close 

    Set ts = Nothing 
    Set fso = Nothing 

    MsgBox "Done" 
End Sub 

    Sub MacroToRunTwo() 
    Dim S As String 
    S = "Hello World From Two:" & vbCrLf & _ 
     "This Add-In File Name: " & ThisWorkbook.FullName 
    MsgBox S 
End Sub 

Function GetDesktopPath() As String 
'Return the current user's desktop path 
GetDesktopPath = "C:\Users\patrick\Desktop\" 
'GetDesktopPath = Environ("HOMEDRIVE") & Environ("HOMEPATH") & "\Desktop\" 
End Function 

而且工作簿代碼:


    Private Const C_TAG = "Refracted Solutions" ' C_TAG should be a string unique to this add-in. 
Private Const C_TOOLS_MENU_ID As Long = 30007& 

Private Sub Workbook_Open() 
''''''''''''''''''''''''''''''''''''''''''''''' 
' Workbook_Open 
' Create a submenu on the Tools menu. The 
' submenu has two controls on it. 
''''''''''''''''''''''''''''''''''''''''''''''' 
Dim ToolsMenu As Office.CommandBarControl 
Dim ToolsMenuItem As Office.CommandBarControl 
Dim ToolsMenuControl As Office.CommandBarControl 

''''''''''''''''''''''''''''''''''''''''''''''' 
' First delete any of our controls that 
' may not have been properly deleted previously. 
''''''''''''''''''''''''''''''''''''''''''''''' 
DeleteControls 

'''''''''''''''''''''''''''''''''''''''''''''' 
' Get a reference to the Tools menu. 
'''''''''''''''''''''''''''''''''''''''''''''' 
Set ToolsMenu = Application.CommandBars.FindControl(ID:=C_TOOLS_MENU_ID) 
If ToolsMenu Is Nothing Then 
    MsgBox "Unable to access Tools menu.", vbOKOnly 
    Exit Sub 
End If 

'''''''''''''''''''''''''''''''''''''''''''''' 
' Create a item on the Tools menu. 
'''''''''''''''''''''''''''''''''''''''''''''' 
Set ToolsMenuItem = ToolsMenu.Controls.Add(Type:=msoControlPopup, temporary:=True) 
If ToolsMenuItem Is Nothing Then 
    MsgBox "Unable to add item to the Tools menu.", vbOKOnly 
    Exit Sub 
End If 

With ToolsMenuItem 
    .Caption = "&WWCares" 
    .BeginGroup = True 
    .Tag = C_TAG 
End With 

'''''''''''''''''''''''''''''''''''''''''''''' 
' Create the first control on the new item 
' in the Tools menu. 
'''''''''''''''''''''''''''''''''''''''''''''' 
Set ToolsMenuControl = ToolsMenuItem.Controls.Add(Type:=msoControlButton, temporary:=True) 
If ToolsMenuControl Is Nothing Then 
    MsgBox "Unable to add item to Tools menu item.", vbOKOnly 
    Exit Sub 
End If 

With ToolsMenuControl 
    '''''''''''''''''''''''''''''''''''' 
    ' Set the display caption and the 
    ' procedure to run when clicked. 
    '''''''''''''''''''''''''''''''''''' 
    .Caption = "State ANSII E&xport" 
    .OnAction = "'" & ThisWorkbook.Name & "'!StateANSIIExport" 
    .Tag = C_TAG 
End With 

'''''''''''''''''''''''''''''''''''''''''''''' 
' Create the second control on the new item 
' in the Tools menu. 
'''''''''''''''''''''''''''''''''''''''''''''' 
'Set ToolsMenuControl = ToolsMenuItem.Controls.Add(Type:=msoControlButton, temporary:=True) 
'If ToolsMenuControl Is Nothing Then 
' MsgBox "Unable to add item to Tools menu item.", vbOKOnly 
' Exit Sub 
'End If 

'With ToolsMenuControl 
    '''''''''''''''''''''''''''''''''''' 
    ' Set the display caption and the 
    ' procedure to run when clicked. 
    '''''''''''''''''''''''''''''''''''' 
' .Caption = "Click Me &Two" 
' .OnAction = "'" & ThisWorkbook.Name & "'!MacroToRunTwo" 
' .Tag = C_TAG 
'End With 

End Sub 


Private Sub Workbook_BeforeClose(Cancel As Boolean) 
'''''''''''''''''''''''''''''''''''''''''''''''''''' 
' Workbook_BeforeClose 
' Before closing the add-in, clean up our controls. 
'''''''''''''''''''''''''''''''''''''''''''''''''''' 
    DeleteControls 
End Sub 


Private Sub DeleteControls() 
'''''''''''''''''''''''''''''''''''' 
' Delete controls whose Tag is 
' equal to C_TAG. 
'''''''''''''''''''''''''''''''''''' 
Dim Ctrl As Office.CommandBarControl 

On Error Resume Next 
Set Ctrl = Application.CommandBars.FindControl(Tag:=C_TAG) 

Do Until Ctrl Is Nothing 
    Ctrl.Delete 
    Set Ctrl = Application.CommandBars.FindControl(Tag:=C_TAG) 
Loop 

End Sub 

0

,正如更新:我能夠用我和所有齧合。這很好。

我將其添加到工具欄菜單中以便於調用,並將保存部分更改爲自動在此處找到桌面並保存文件。追加通過已過濾的輸入框輸入的Quarter YEar變量的值。

我想嘗試擺脫他們不得不選擇活動區域,但根據所涉及的工作,這可能不值得我花時間進行投資。 (Solo店和所有)沿着同樣的路線,它會很高興有更多的錯誤捕捉,因爲它是目前相當脆弱,但唉....

再次感謝!

相關問題