Экспорт диапазона / листа Excel в форматированный текстовый файл - PullRequest
2 голосов
/ 23 января 2009

Передо мной была поставлена ​​задача создать для нашего финансового отдела процесс многократного использования, чтобы загрузить нашу платежную ведомость в штат (WI) для отчетности. Мне нужно создать что-то, что берет лист или диапазон в Excel и создает специально отформатированный текстовый файл.

ФОРМАТ

  • Столбец 1 - Статический номер, никогда не изменяется, позиция 1-10
  • Столбец 2 - Динамический параметр, заполненный во время выполнения для квартала / года, позиция 11-13
  • Колонка 3 - SSN, без дефисов и пробелов, заполнено из столбца А, позиция 14-22
  • Колонка 4 - Фамилия, заполнена из столбец B, усеченный на 10, слева Обоснуйте и заполните пробелами, положение 23-32
  • Колонка 5 - Имя, заполнено буквой C, Обрезать в 8, левый Justify & fill с заготовками, позиция 33-40
  • Колонка 6 - Общая валовая заработная плата / квартал, заполнено от D, лишить все форматирование, Правое обоснование заполнения нуля, позиция 41-49
  • Колонка 7 - Статический код, никогда изменения, позиция 50-51
  • Колонка 8 - Бланки, Заполните пробелы, позиция 52-80

У меня есть, я полагаю, 3 варианта:

  1. VBA
  2. .NET
  3. SQL

Сначала я изучил метод .NET, но просто не смог найти достойную документацию, которая бы мне помогала. Мне все еще нравится этот, но я отвлекся.

Далее у меня есть несколько VBA, которые будут выгружать лист в текст фиксированной ширины. В настоящее время я занимаюсь этим, что в конечном итоге приводит к моему актуальному вопросу.

Как мне преобразовать диапазон текста в Excel? Нужно ли мне перенести его на другой лист, а затем передать эти данные с необходимыми функциями форматирования для запуска подпрограммы Dump to text? В настоящее время я планировал создать функцию для каждого столбца, но у меня возникли проблемы с выбором следующего шага. Я довольно новичок в программировании и разработке Office в целом, поэтому любая оценка будет принята с благодарностью.

Вариант SQL был бы моим откатом, так как в прошлом я выполнял аналогичный экспорт из SQL. Я просто предпочитаю два других на «Я не хочу отвечать за это», принцип .

Заранее благодарим за предоставленное время.

Ответы [ 5 ]

4 голосов
/ 25 января 2009

Использование 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), "!@@@@@@@@@@")
strPayrollReportLine = strPayrollReportLine & strCleanLastName

strRawFirstName = rngPayrollData.Cells(indexRow, 3)
strCleanFirstName = Format(Left$(strRawFirstName, 8), "!@@@@@@@@")
strPayrollReportLine = strPayrollReportLine & strCleanFirstName

Left$(string, length) усекает строку до заданной длины. Формат изображения !@@@@@@@@@@ форматирует строку длиной ровно десять символов, выравнивание по левому краю (! Означает выравнивание по левому краю) и с пробелами

' 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 для генерации правильного значения. Это не даст правильного вывода для заработной платы> = 10 миллионов долларов, но это ограничение формата файла, используемого для отчетности. * * * * * * * * * * * * * * * * * * * *

в форматных планшетах формата с нулями на удивление достаточно.
' 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) создает вариант с последовательностью number указанного char. CStr превращает вариант в строку. Оператор 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 возвращает длину строки, а Mid$(string, start, length) возвращает length символов, начиная с string, начиная с start. Эту функцию можно улучшить, так как в настоящее время она не проверяет нечисловые данные

Для вызова макроса:

Sub CallPayrollReport()

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

End Sub

Это самый простой способ назвать это. Диапазон - это то, что пользователь выбрал на активной рабочей таблице в активной рабочей книге, а остальные значения жестко запрограммированы. Пользователь должен выбрать диапазон, который он хочет вывести в файл, затем перейдите в Инструменты> Макрос> Выполнить и выберите CallPayrollReport. Чтобы это работало, макрос должен быть частью рабочей книги, содержащей данные, или другой книгой, которая была загружена до того, как пользователь вызовет макрос.

Кто-то должен будет изменить жестко закодированное значение квартала / года, прежде чем будет сгенерирован отчет за каждый квартал. Как указывалось ранее, если квартал / год уже сохранен где-то в рабочей книге, лучше прочитать его, а не жестко кодировать его

Надеюсь, что это имеет смысл и имеет некоторое значение

0 голосов
/ 25 января 2009

Так же, как обновление: я смог связать это с моим, и все хорошо.

Я добавил это в меню панели инструментов для удобного вызова и изменил часть сохранения, чтобы автоматически найти там рабочий стол и сохранить файл. Присоединение значения переменной Quarter YEar, которую они вводят через отфильтрованное поле ввода.

Я хотел бы попытаться избавить их от необходимости выбирать активную область, но в зависимости от выполняемой работы это может не стоить моих временных затрат. (Магазин соло и все остальное). В том же духе было бы неплохо иметь больше ошибок, поскольку в данный момент это довольно хрупко, но увы ....

Еще раз спасибо!

0 голосов
/ 25 января 2009

Вау!

Я должен сказать, я взорван. Вы до сих пор превзошли мои ожидания в отношении ответа, и я чувствую вину за то, что могу ТОЛЬКО проголосовать один раз за вас и пометить как исключенный. У меня была НАДЕЖДА на то, чтобы получить представление о том, какой путь лучше и какое форматирование. Ну с Днем Рождения меня!

Format () и FreeFile () были особенно новой полезной информацией. Кроме того, просто чтобы показать, что я пытался, моя попытка ниже. Я был довольно близок, так как я только прорабатывал детали форматирования, но я верю, что переделаю это с вашим вкладом, так как это кажется более элегантным подходом.

В качестве последнего примечания. Я нашел это место в блоге Джеффа Этвуда, и я был действительно взволнован этой идеей. Как новый, неопытный разработчик в магазине соло, я всегда хотел, чтобы было место, куда я мог бы обратиться за наставничеством. Книги и статьи помогают вам понять, но ничто не сравнится с советом того, кто это сделал или был там. Пока 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 голосов
/ 23 января 2009

Обдумывая это строго с точки зрения того, что для вас проще всего, и, если вы знакомы с SQL, в контексте Access вы можете использовать Access для подключения к электронной таблице в качестве внешнего источника данных. Это будет выглядеть как таблица в Access, и работать оттуда.

0 голосов
/ 23 января 2009

В зависимости от формата вашего документа, я, вероятно, рекомендую экспортировать в .csv и работать с этим. Если вам нужны только цифры, это будет самый простой способ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...