Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 72 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
72
Dung lượng
2,23 MB
Nội dung
FIGURE 3.5 A dialog form for selecting Northwind Orders data to archive. FIGURE 3.6 Selecting a date from the calendar pop-up. Once the start date and end date have been entered or selected, clicking the Archive button runs a procedure that creates a new Excel worksheet from a template (Orders Archive.xltx) in the same folder as the database, fills it with data from tblOrders in the selected date range, and deletes the archived records. The ArchiveData procedure uses the Start Date and End Date values selected in the dialog as arguments. This procedure is listed as follows, together with the CreateAndTestQuery proce- dure it uses to create a query programmatically, and another procedure ( TestFileExists) that tests whether a file exists in a specific folder: Public Sub ArchiveData(dteStart As Date, dteEnd As Date) On Error GoTo ErrorHandler Dim appExcel As Excel.Application Dim intReturn As Integer Dim lngCount As Long Dim n As Long 53 Analyzing Data with Excel 3 07_047026 ch03.qxp 4/2/07 9:42 PM Page 53 Dim rng As Excel.Range Dim rngStart As Excel.Range Dim strDBPath As String Dim strPrompt As String Dim strQuery As String Dim strSaveName As String Dim strSheet As String Dim strSheetTitle As String Dim strSQL As String Dim strTemplate As String Dim strTemplateFile As String Dim strTemplatePath As String Dim strTitle As String Dim wkb As Excel.Workbook Dim wks As Excel.Worksheet Create a filtered query using the dates selected in the dialog: strQuery = “qryArchive” Set dbs = CurrentDb strSQL = “SELECT * FROM tblOrders WHERE “ _ & “[ShippedDate] Between #” & dteStart & “# And #” _ & dteEnd & “#;” Debug.Print “SQL for “ & strQuery & “: “ & strSQL lngCount = CreateAndTestQuery(strQuery, strSQL) Debug.Print “No. of items found: “ & lngCount If lngCount = 0 Then Exit if no orders are found in the selected date range: strPrompt = “No orders found for this date range; “ _ & “canceling archiving” strTitle = “Canceling” MsgBox strPrompt, vbOKOnly + vbCritical, strTitle GoTo ErrorHandlerExit Else strPrompt = lngCount & “ orders found in this date “ _ & “range; archive them?” strTitle = “Archiving” intReturn = MsgBox(strPrompt, vbYesNo + vbQuestion, _ strTitle) If intReturn = vbNo Then GoTo ErrorHandlerExit End If End If Create a new worksheet from the template and export the Access data to it: strDBPath = Application.CurrentProject.Path & “\” Debug.Print “Current database path: “ & strDBPath 54 The Office Components and What They Do Best Part I 07_047026 ch03.qxp 4/2/07 9:42 PM Page 54 strTemplate = “Orders Archive.xltx” strTemplateFile = strDBPath & strTemplate If TestFileExists(strTemplateFile) = False Then Put up a message and exit if the template is not found: strTitle = “Template not found” strPrompt = “Excel template ‘Orders Archive.xlt’” _ & “ not found in “ & strDBPath & “;” & vbCrLf _ & “please put template in this folder and try again” MsgBox strPrompt, vbCritical + vbOKOnly, strTitle GoTo ErrorHandlerExit Else Debug.Print “Excel template used: “ & strTemplateFile End If Template found; create a new worksheet from it: Set appExcel = GetObject(, “Excel.Application”) Set rst = dbs.OpenRecordset(“qryRecordsToArchive”) Set wkb = appExcel.Workbooks.Add(strTemplateFile) Set wks = wkb.Sheets(1) wks.Activate appExcel.Visible = True Write the date range to title cell: Set rng = wks.Range(“A1”) strSheetTitle = “Archived Orders for “ _ & Format(dteStart, “d-mmm-yyyy”) _ & “ to “ & Format(dteEnd, “d-mmm-yyyy”) Debug.Print “Sheet title: “ & strSheetTitle rng.Value = strSheetTitle Go to the first data cell: Set rngStart = wks.Range(“A4”) Set rng = wks.Range(“A4”) Reset lngCount to the number of records in the data source query: rst.MoveLast rst.MoveFirst lngCount = rst.RecordCount For n = 1 To lngCount Write data from the recordset to the data area of the worksheet, using the columnoffset argu- ment to move to the next cell: 55 Analyzing Data with Excel 3 07_047026 ch03.qxp 4/2/07 9:42 PM Page 55 rng.Value = Nz(rst![OrderID]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![Customer]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![Employee]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![OrderDate]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![RequiredDate]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![ShippedDate]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![Shipper]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![Freight]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![ShipName]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![ShipAddress]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![ShipCity]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![ShipRegion]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![ShipPostalCode]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![ShipCountry]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![Product]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![UnitPrice]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![Quantity]) Set rng = rng.Offset(columnoffset:=1) rng.Value = Nz(rst![Discount]) Go to the next row in the worksheet, using the rowoffset argument: rst.MoveNext Set rng = rngStart.Offset(rowoffset:=n) Next n Save and close the filled-in worksheet, using a workbook save name with the date range selected in the dialog: strSaveName = strDBPath & strSheetTitle & “.xlsx” Debug.Print “Time sheet save name: “ & strSaveName 56 The Office Components and What They Do Best Part I 07_047026 ch03.qxp 4/2/07 9:42 PM Page 56 ChDir strDBPath On Error Resume Next If there already is a saved worksheet with this name, delete it: Kill strSaveName On Error GoTo ErrorHandler wkb.SaveAs FileName:=strSaveName, _ FileFormat:=xlWorkbookDefault wkb.Close rst.Close Put up a success message, listing the name and path of the new worksheet: strTitle = “Workbook created” strPrompt = “Archive workbook ‘“ & strSheetTitle & “‘“ _ & vbCrLf & “created in “ & strDBPath MsgBox strPrompt, vbOKOnly + vbInformation, strTitle Delete the archived records, processing the “many” table first, because you can’t delete a record in the “one” table if there are linked records in the “many” table: DoCmd.SetWarnings False strSQL = “DELETE tblOrderDetails.*, “ _ & “tblOrders.ShippedDate “ _ & “FROM tblOrderDetails INNER JOIN qryArchive “ _ & “ON tblOrderDetails.OrderID = qryArchive.OrderID;” Debug.Print “SQL string: “ & strSQL DoCmd.RunSQL strSQL strSQL = “DELETE tblOrders.* FROM tblOrders WHERE “ _ & “[ShippedDate] Between #” & dteStart & “# And #” _ & dteEnd & “#;” Debug.Print “SQL string: “ & strSQL DoCmd.RunSQL strSQL Put up a message listing the cleared records: strTitle = “Records cleared” strPrompt = “Archived records from “ _ & Format(dteStart, “d-mmm-yyyy”) _ & “ to “ & Format(dteEnd, “d-mmm-yyyy”) _ & “ cleared from tables” MsgBox strPrompt, vbOKOnly + vbInformation, strTitle ErrorHandlerExit: Exit Sub 57 Analyzing Data with Excel 3 07_047026 ch03.qxp 4/2/07 9:42 PM Page 57 ErrorHandler: ‘Excel is not running; open Excel with CreateObject If Err.Number = 429 Then Set appExcel = CreateObject(“Excel.Application”) Resume Next Else MsgBox “Error No: “ & Err.Number & “; Description: “ Resume ErrorHandlerExit End If End Sub Public Function CreateAndTestQuery(strTestQuery As String, _ strTestSQL As String) As Long This function is called from other procedures to create a filtered query, using a SQL string in its strTestSQL argument: On Error Resume Next Dim qdf As DAO.QueryDef ‘Delete old query Set dbs = CurrentDb dbs.QueryDefs.Delete strTestQuery On Error GoTo ErrorHandler ‘Create new query Set qdf = dbs.CreateQueryDef(strTestQuery, strTestSQL) ‘Test whether there are any records Set rst = dbs.OpenRecordset(strTestQuery) With rst .MoveFirst .MoveLast CreateAndTestQuery = .RecordCount End With ErrorHandlerExit: Exit Function ErrorHandler: If Err.Number = 3021 Then CreateAndTestQuery = 0 Resume ErrorHandlerExit Else MsgBox “Error No: “ & Err.Number & “; Description: “ & Err.Description Resume ErrorHandlerExit End If 58 The Office Components and What They Do Best Part I 07_047026 ch03.qxp 4/2/07 9:42 PM Page 58 End Function Public Function TestFileExists(strFile As String) As Boolean On Error Resume Next TestFileExists = Not (Dir(strFile) = “”) End Function The code in the sample database requires a reference to the Excel object library; Figure 3.7 shows this reference checked in the References dialog, which is opened from the Tools menu in the Visual Basic window. FIGURE 3.7 Setting a reference to the Excel object model. After the worksheet of archived records has been created and saved, you will get a message (depicted in Figure 3.8) listing the location where the archive worksheet was saved. FIGURE 3.8 A success message after records are archived. NOTE NOTE 59 Analyzing Data with Excel 3 07_047026 ch03.qxp 4/2/07 9:42 PM Page 59 See Chapter 7 for a more flexible way of specifying a Templates folder and a Documents folder. After the code deletes the archived records — first the ones in tblOrderDetails (the “many” table) and then those in tblOrders (the “one” table) — a final message appears, as shown in Figure 3.9. FIGURE 3.9 A final informative message stating that the archived database records have been cleared. A worksheet filled with archived data is shown in Figure 3.10. FIGURE 3.10 A worksheet filled with archived Access data. Saving the newly created worksheet with the xlWorkbookDefault value for the FileFormat argument saves it as a standard Excel worksheet. If you need to save the worksheet in another for- mat, perhaps for use by someone running an older version of Excel, you can use one of the other values in the XlFileFormat enum, which are shown in the Object Browser in Figure 3.11. The xlExcel9795 named constant will create a worksheet in a format usable by people running Excel 95 or 97. (The worksheet format choices available in VBA code are much more numerous than those available in the interface, as shown in Figure 3.12.) NOTE NOTE 60 The Office Components and What They Do Best Part I 07_047026 ch03.qxp 4/2/07 9:42 PM Page 60 FIGURE 3.11 Viewing the file format choices for saving an Excel workbook. If you create a worksheet in the new .xlsx format, only Office 2007 users will be able to open it. To create a worksheet that can be opened and edited by users with earlier versions of Office, select one of the other formats. The Excel 97–Excel 2003 Workbook (.xls) format (shown being selected in Figure 3.12) is usable in Office 97 through 2007, so it is generally the most useful worksheet format. FIGURE 3.12 Selecting a worksheet save format. WARNING WARNING 61 Analyzing Data with Excel 3 07_047026 ch03.qxp 4/2/07 9:42 PM Page 61 To open the Object Browser for examining components of an object model, open the Visual Basic window and select Object Browser from the View menu, or press F2. Formatting Excel Worksheets in VBA Code If you need to sort, group, indent, or otherwise format exported data in an Excel worksheet, or cre- ate a total under the last row of data, you can write VBA code to use Excel commands to do the work in code. You can apply formatting to a worksheet created by the TransferSpreadsheet method, or one created from the Ribbon command, or a worksheet created programmatically from a template. See Chapter 7 for examples of creating worksheets using the TransferSpreadsheet method. In this section, data from qryOrdersAndDetails is exported to a new worksheet made from a tem- plate and is then formatted in code. For convenience, the ExportNorthwindData procedure can be run from the macro mcrExportNorthwindData. The procedure starts by creating a new worksheet from a template (Northwind Orders.xltx), as for the ArchiveData procedure. Data from the query qryOrdersAndDetails is written to rows in the worksheet, and then a set of Excel commands is used to apply hairline borders to the data area, and a double bottom border to the column headings row. Next, the worksheet’s data area is sorted by the first two columns (Country and Category), and the extra values are removed (the effect is similar to turning on Hide Duplicates in an Access report). Finally, a Grand Total is created under the last row, made large and bold, and enclosed in a box. The procedure is listed as follows: Public Sub ExportNorthwindData() On Error GoTo ErrorHandler Dim appExcel As Object Dim i As Integer Dim lngCount As Long Dim lngCurrentRow As Long Dim lngRows As Long Dim n As Long Dim objFind As Object Dim rng As Excel.Range Dim rngData As Excel.Range Dim rngStart As Excel.Range Dim strCategory As String Dim strCountry As String Dim strCurrAddress As String Dim strDBPath As String Dim strFormula As String CROSS-REF CROSS-REF NOTE NOTE 62 The Office Components and What They Do Best Part I 07_047026 ch03.qxp 4/2/07 9:42 PM Page 62 [...]... IN THIS CHAPTER Creating Outlook appointments and tasks from Access data Writing Access data to the Outlook Journal Creating emails to contacts in an Access table Part I The Office Components and What They Do Best If you store email addresses in a table of contacts, customers, or clients, you can use VBA code to create emails to them from an Access form, either to a single recipient or a group of recipients,... tasks, appointments, email messages, or journal items from data in Access tables, allowing you to use Access as a control center, while making use of Outlook items where they offer a superior interface, or are more widely accessible for users 85 4 Writing VBA Code to Exchange Data between Office Components IN THIS PART Chapter 5 Working with Access Data Chapter 6 Working with Word Documents and Templates... folder is called a calendar), the Outlook interface is so superior that I recommend not trying to replicate its functionality in Access, but instead to export Access data to Outlook, creating email messages, appointments, or other Outlook items as needed Way back in Access 2. 0, I created a database to manage tasks, allowing me to assign them priorities, start and due dates, and notes, and order them... because Outlook includes its own Task List (or To Do List, as it is labeled in Office 20 07) All the features I wanted were built in to the Outlook Task List, so I moved all my tasks to Outlook and managed them with Outlook’s tools Because Outlook does such a good job with tasks, there is no need to store task data in Access, though in some special circumstances you might need to do this, and then perhaps... Analyzing Data with Excel If Err.Number = 429 Then Set appExcel = CreateObject(“Excel.Application”) Resume Next Else MsgBox “Error No: “ & Err.Number & “; Description: “ _ & Err.Description Resume ErrorHandlerExit End If End Sub A finished worksheet is shown in Figure 3.13 FIGURE 3.13 A worksheet filled with data and formatted using VBA code Summary When you need to export Access data to Excel worksheets so... capabilities of Access This means you need a way to synchronize data between Outlook and Access contacts; my Synchronizing Contacts.accdb database does just this CROSS-REF See Chapter 11 for a discussion of the Synchronizing Contacts database Chapter 8 deals with exporting and importing contacts without synchronization This chapter concentrates on exporting tasks, appointments, and journal items from Access. .. concentrates on exporting tasks, appointments, and journal items from Access to Outlook and creating emails to contacts stored in an Access table NOTE The sample database for this chapter is Access to Outlook.accdb Exporting Appointments and Tasks to Outlook If you have an Access table of employee, contact, or customer information, you may need to create Outlook appointments or tasks based on information... strTitle ErrorHandler: ‘Outlook is not running; open Outlook with CreateObject If Err.Number = 429 Then Set appOutlook = CreateObject(“Outlook.Application”) Resume Next Else MsgBox “Error No: “ & Err.Number _ & “; Description: “ & Err.Description Resume ErrorHandlerExit End If End Function NOTE When Outlook 20 07 is first installed, the Journal component is turned off; activate it in order to see the... FIGURE 4.6 A journal item created from a record in a table of mainframe transaction data Creating Emails from an Access Table If you have an Access table (say, of customer, client, or contact information) with email addresses, you can create emails to people in the table directly from an Access form, so you don’t need to open Outlook to create an email, which can save time tblContacts in the sample... 1).Font.ColorIndex = 2 ElseIf rng.Cells(i, 1).Value strCategory Then Debug.Print “Different data in “ _ & rng.Cells(i, 1).Address strCategory = rng.Cells(i, 1).Value End If Next i 66 Analyzing Data with Excel Add a Grand Total, and format its cell: strFormula = “=SUM(R[-” & CStr(lngRows - 2) _ & “]C:R[-1]C)” Debug.Print “Formula: “ & strFormula strRange = “I” & CStr(lngRows + 2) Debug.Print “Range: . VBA code are much more numerous than those available in the interface, as shown in Figure 3. 12. ) NOTE NOTE 60 The Office Components and What They Do Best Part I 07_047 026 ch03.qxp 4 /2/ 07 9: 42. strFormula As String CROSS-REF CROSS-REF NOTE NOTE 62 The Office Components and What They Do Best Part I 07_047 026 ch03.qxp 4 /2/ 07 9: 42 PM Page 62 Dim strPrompt As String Dim strDataRange As String Dim. using VBA code, either to a plain default worksheet, or a formatted worksheet created from an Excel template. 69 Analyzing Data with Excel 3 07_047 026 ch03.qxp 4 /2/ 07 9: 42 PM Page 69 07_047 026 ch03.qxp