More SOL- Salutions to Common Problems
Total Page:16
File Type:pdf, Size:1020Kb
APPENDIX A More SOL- Salutions to Common Problems Problem 1: Begin a Label Report at Any Label on the Sheet MosT LABEL RuNs leave unused labels an the last sheet. The following technique will start a label run at a specific label position, so you can use those partially used sheets. The components are a form, a temporary table, and a label report. You'll use the form to identify the position of the first available label. Then, an event procedure will populate the temporary table with blank rows, with one blank row for each missing label. The number of blank rows is determined by the value you enter. Ifyou enter a value of 3 (meaning that the first label is in the third label position), the procedure will add two blank rows. Next, the procedure appends the label data below the blank rows. The report doesn't care that the rows are empty; the positions are still filled in the label report. Each blank row represents a blank label, pushing the actual data down to the first label. This technique doesn't accommodate missing labels between the first and last label. Example: tblOne, frmOne, and rptOne Solution 1: SELECT, DELETE, and INSERT INTO Ta create the temporary table: 1. In the Database window, select the table that contains the data you're printing. 2. Press Ctr1 +C to copy the table to the clipboard. 3. Press Ctrl+V topaste a copy ofthe table. In the Paste Table As dialag box, enter a name for the dummy table. (We'll be working with tblOne.) Select the Structure Only option button in the Paste Options section, and dick onOK. 655 AppendixA 4. Open tblOne and delete any primary key. Don't delete the fields; just delete the primary key. 5. Review the Indexed and Required properties for each field and make sure that each is set to No. 6. Save the table. To create the form: 1. Open a new, unbound form in Design view. 2. Insert a textbox and enter an appropriate label caption. 3. Name the textbox txtBlankRows. 4. Insert two command buttons, side by side. 5. Name them cmdPrint and cmdCancel and set their Caption properties to Print and Cancel, respectively. 6. Click on the Code button on the Form Design toolbar to launch the Visual Basic Editor. 7. In the form's module, enter the following event procedures: Private Sub crndPrint_Click() Dirn rst As New ADODB.Recordset Dirn bytCounter As Byte Dirn bytBlanks As Byte On Error GoTe errHandler bytBlanks = Forrns!frmOne!txtBlankRows.Value DoCrnd.SetWarnings False DoCrnd. RunSQL "DELETE FROM nameoftemporarytable" Set rst.ActiveConnection = CurrentProject.Connection rst.Open "SELECT * FROM nameoftemporarytable ", , _ adOpenDynarnic, adlockOptirnistic For bytCounter = 2 To bytBlanks rst.AddNew rst.Update Next rst.Close Set rst = Nothing 656 More SQL Salutions to Common Problems DoCmd.RunSQL "INSERT INTO nameoftemporarytable " & "SELECT * FROM datatable" DoCmd.SetWarnings True DoCmd.OpenReport "nameoflabelreport", acViewPreview Exit Sub errHandler: MsgBox "Please enter a valid label number" DoCmd.SetWarnings True End Sub Private Sub cmdCancel_Click() DoCmd.Close acForm, "nameofform", acSaveNo End Sub 8. Save the form. The example form is named frmOne. Because the label report will be unique to your application, we won't build one. The example file uses a label report named rptOne, based on the Customers table in Northwind. Before running the report, insert your label sheets into the printer. Be sure to position the partially used sheet as the first sheet. Then, open the form (frmOne) and enter the position of the first existing label. (For instance, if two labels were missing, you'd enter the value 3, and, if six labels were missing, you'd enter the value 7.) Then, dick on the Print button, and the event procedure prints the report. Problem 2: Finding the Second-Highest or -Lowest Value in a Group Querying for the second-highest or second-lowest value in a tableis easy, and it requires two queries. First, you identify the data source and the fields you want to see in the results. Then, you set the sort order, ascending for the highest and descending for the lowest. Then, set the Top Values property to 2 so that the query returns only the highest and second-highest or the lowest and second lowest values, depending on the sort order. Base the second query on the first query, set the Top Values property to 1, and reverse the sort order. This technique is complicated when you need toreturn the second-highest or second-lowest value in a group, and the solution again requires two queries. 657 AppendixA Example: qryOneFirstQuery, qryTwoSecondQuery Solution 2: GROUP BY To create the first query: 1. Base a Totals query on the data source. Be careful to use only those fields that identify each group. To manually define a Totals query, choose Totals from the View menu in the Query Design toolbar. Specify the Max aggre gate in the grouping value's total cell, or, in the SQL window, add a GROUP BY clause in the form: SELECT groupedfield, Max(valuefield) AS name FROM table GROUP BY groupedfield where groupedfield represents the field(s) by which you're grouping, valuefield is the field with the values you're sorting in order of largest to smallest, name is the alias column name for valuefield, and tableis the data source. 2. Save the query using an appropriate name. Our example query is qryTwoFirstQuery. 3. Base a second query on your data source and add the first query (qryOneFirstQuery) to it. Open the SQL window and use an SQL state ment in the form SELECT dsgroupedfield, qrygroupedfield, Max(dsvaluefield) AS name FROM ds LEFT JOIN query ON (dsvaluefield = name) AND (dsgroupedfield = qrygroupedfield) GROUP BY dsgroupedfield, qrygroupedfield HAVING qrygroupedfield Is Null where dsgroupedfield is the grouped field in the data source, qrygroupedfield is the grouped field in the first query, ds is the data source, and query is the first query. Or, create the query manually by following steps 4 through 9. 4. Create a relationship for the grouped fields and the value fields between the data source and the query. Remember, the value field's name will probably be different in the query. 658 More SQL Salutions to Common Problems 5. Add both grouped fields to the query (from the data source and the query). Also add the value field from the data source. 6. Make the query a Totals query by choosing Totals from the View menu. 7. Change the value field's Totalsaggregate from Group By to Max. 8. Add the criteria Is Null to the query's (qryTwoFirstQuery) group field. 9. Save the query. We saved the example file as qryTwoSecondQuery. To see the results, run qryTwoSecondQuery. These instructions return a list ofthe second-highest product for each order in the Order Details table. Simply change the Max aggregate to the Min aggregate in both queries. Problem 3: Adding a Summary Row to a Query We often see tatals in a form or report, but you can also view tatals in a query. This technique is more limited than the form or report solutions, but it's extremely easy: simply use a Union query to append a single row of aggregate functions to a SELECT query. The number of columns for each SELECT must match. Example: qryThree Solution 3: Union Query To create the Union query: 1. Base a query on the data source. 2. Add the appropriate fields to the query. 3. Open the SQL window and add to the existing SELECT statement a UNION clause in the form UNION SELECT agg(fld1), agg(fld2), FROM ds where aggis one ofthe aggregate functions,jldxrepresents a field from the original SELECT clause, and ds is the data source. 659 AppendixA 4. Save the query. The example file is named qryThree. The totals row will appear as the first or last row in the query's results, depending on how it sorts. Each field in the original Select query must be represented in the Union query, either by entering an aggregate function, a delimited string, or a zero length string (""). For instance, the following Statementdisplays the string "Averages" in the first column, and the result of aggregate functions in the remaining columns: SELECT OrderiD, UnitPrice, Quantity, Discount FROM [Order Details] UNION SELECT 'Averages', Avg{UnitPrice), Avg(Quantity), Avg( Discount) FROM [Order Details] lfyou use "" to represent the first column, Jet would sort the averaged row first in the resultset: SELECT OrderiD, UnitPrice, Quantity, Discount FROM [Order Details] UNION SELECT "", Avg{UnitPrice), Avg{Quantity), Avg(Discount) FROM [Order Details] Problem 4: Returning Alternating Rows Returning alternating rows-either oddly or evenly numbered-is a simple task if your table includes an AutoNumber field. The solution uses the MOD operator and sequential values in an AutoNumber field. Example: qryFourEven, qryFourOdd Solution 4: MOD Operator To return a table of oddly numbered records, use a Statement in the form SELECT fldlist FROM tbl WHERE AutoNumberfield Mod 2<>0 660 More SQL Salutions to Common Problems Toreturn a table of even-numbered records, use a statement in the form SELECT fldlist FROM tbl WHERE AutoNumberfield Mod 2=0 If no AutoNumber field exists, you can temporarily add one using the ALTER TABLE statement in the following form: ALTER TABLE tbl ADD COLUMN fldname AUTOINCREMENT Run one of these preceding Statements and then delete the temporary AutoNumber field using the DROP COLUMN clause in the form ALTER TABLE table DROP COLUMN fldname Problem s: Producing a Random Sort There's no way to create a truly random sort in Access, but you can return a seemingly random set.