Can you populate Classic ASP Constants (CONST) dynamically? - arrays

I am wishing to replace an include file with ~ 25 declared Constants by dynamically creating those constants from a Recordset (or Array). I have tried looping through a record set and have also tried populating a 2D array and then trying to set these Constants from the array values but it seems to take what is after the "Const" literal and not the value.
If (not rsVars.Eof) Then
cCount = rsVars.RecordCount
ReDim cArray(cCount - 1, 1)
For i = 0 To cCount - 1
cArray(i, 0) = rsVars("VariableNm")
cArray(i, 1) = rsVars("Value")
rsVars.MoveNext
Next
End If
For i = 0 To cCount - 1
' Display the Array Elements - WORKS and Displays All Variables and Desired Values
Response.write "("&(i+1)&") " & cArray(i, 0) & " = " & cArray(i, 1) & "<br>"
' Attempt to set Constant Variables - this next line errors - "Name_redefined"
Const cArray(i, 0) = cArray(i, 1)
Next

You could use the server.execute method to achieve this.
But it needs a FILE path to do so.
You will need to create a file dynamically using the FileSystemObject and pass the file's full path to the server.execute method to make those variables available as constants.
ex:
constants.asp
Note
Values will be CONSTANT Across user sessions and requests.
If you need a different set of constants by user, company, date etc, you will need to change the filename to include the unique constants-.asp and execute that file.
References
https://www.w3schools.com/asp/met_execute.asp
https://www.w3schools.com/ASP/asp_ref_filesystem.asp

Related

Loops in Access VBA

I'm kind of new to Access VBA and I’m having issues with my loop.
I have reviewed various books, websites, asked various friends. Currently I’m trying to have a user input two characters, and then if the two characters equal a certain combination then it is supposed to equal a numeric value, and then use the value in a distance calculation.
The user inputed values are strings and everything else is declared as double.
I have 200+ combinations that I am testing and have tried case statements, DLookup, do while, do until, if, and elseif loops with no success.
I'm also limited by IT and I’m unable to use DAO code.
Any assistance would be greatly appreciated.
I would first suggest creating a table to formally define the various character combinations and the corresponding value for each combination. This has the advantage that the combinations may be easily maintained going forward, rather than defining such combinations as part of queries or in VBA code.
Such a table could be as simple as containing three fields:
Character 1 (Text)
Character 2 (Text)
Value (Number)
You could then populate such a table with your valid combinations:
With the combinations rigorously defined, you have many options regarding how to prompt the user to enter the two characters and obtain the correponding value.
A very simplistic approach might be to use a form with three textboxes:
Here, the first two textboxes would be unbound, and might be called char1 and char2, and the third textbox might be called result and have a Control Source property equal to:
=DLookup("Value", "LookupTable", "char1 = '" & [char1] & "' and char2 = '" & [char2] & "'")
This would yield the following behaviour:
Consider using Access as a database and GUI application by storing your 200+ combinations in a table with corresponding numeric value. Then have an SQL query filter by user input and use resulting value for needed calculations. Below requires creating and using four Access objects: table, query, form, and module.
Table (tblCombinations)
id combn1 combn2 numeric_value
1 A B 150
2 C D 225
3 E F 100
4 G H 75
5 I J 200
...
SQL (no loops needed; using Access form control values)
SELECT c.combn1, c.combn2, c.numeric_value
FROM tblCombinations c
WHERE c.combn1 = Forms!myForm!myUserInputField1
AND c.combn2 = Forms!myForm!myUserInputField2
And even pass needed numeric value in distance calculation formula which can be a VBA function in a standard module:
SELECT c.combn1, c.combn2, Distance_Calculation(c.numeric_value) As distance_result
FROM tblCombinations c
WHERE c.combn1 = Forms!myForm!myUserInputField1
AND c.combn2 = Forms!myForm!myUserInputField2
VBA (place in standard module)
Public Function Distance_Calculation(num_value As Long) As Double
...
Distance_Calculation = some_value
End Function
You can use following type function in your result form button or after event on both textboxes-
Dim resultValue as Integer
If DCount("numeric_value", "tblCombinations", "[combn1] = '" & Forms!myForm!myUserInputField1 & "' and [combn2] = '" & Forms!myForm!myUserInputField2 & "'") > 0 then
resultValue = Dlookup("numeric_value", "tblCombinations", "[combn1] = '" & Forms!myForm!myUserInputField1 & "' and [combn2] = '" & Forms!myForm!myUserInputField2 & "'")
txtResult = Distance_Calculation(resultValue)
Else
Msgbox "No such combination exist. Kindly check combimation", vbinformation, "Information"
txtResult = 0
End if

VBA assign Formula to Variable then use the Variable to evaluate the Formula

I require some help please.
Using Excel 2007.
I'm not even sure this can be done.
I need to maintain efficiency and speed else the application will not be used.
I have a 'IF' statement to test for a criteria.
depending on the results want to assign one of several possible Formulas to a Variable for later use.
I then need to have the Variable to Evaluate the Formula so that the result can be stored in a second variable to build an array.
Sample Code:
If (varEmployeeName = "(All)" Or varEmployeeName = "(Multiple Items)") Then
**varArrayFormula = "Application.WorksheetFunction.SumIfs(wsSumRange, wsLookupRange, wsLookupValue)"**
Else
**varArrayFormula = "Application.WorksheetFunction.SumIfs(wsSumRange, wsLookupRange, wsLookupValue, wsLookupRange2, varEmployeeName)"**
Then Later on this code will execute:
ReDim varKPIArray(0 To varLastRow) ' creates the array size
For varCol = 10 To 13
For varRow = 8 To varLastRow
varDailyKPIHeading = ws.Cells(7, varCol).Value
Select Case varDailyKPIHeading
Case "PRODUCTIVITY"
Set wsSumRange = ThisWorkbook.Worksheets("DailyProductivity").Range("$G:$G")
Set wsLookupRange = ThisWorkbook.Worksheets("DailyProductivity").Range("$F:$F")
wsLookupValue = ws.Range("B" & varRow).Value
**varSumifValue = Application.Evaluate(varArrayFormula)**
varKPIArray(varRow - 8) = varSumifValue
Case "HOURS"
The program will then loop through several columns and rows hence why the variables are needed. I have 2 options at this point:
1) is to build an array and then I can paste the array results in the appropriate cells with a second loop.
or
2) As I am loop through each cell I Populate the formula results to the cell
Thank you everyone for you help, suggestions and ideas
Use this as your formula strings:
"SumIfs(" & wsSumRange.Address(0,0) & "," & wsLookupRange.Address(0,0) & "," & wsLookupValue & ")"
And:
"SumIfs(" & wsSumRange.Address(0,0) & "," & wsLookupRange.Address(0,0) & "," & wsLookupValue & "," & wsLookupRange2.Address(0,0) & "," & varEmployeeName & ")"
Thanks to all who gave their suggestions and Help.
Ultimately i was not able to get anything to work and ended up designing and rewriting the code.
It was hoped that there was a simply solution of applying a Formula with variables to a variable so that one did not have to keep retyping the formula and could just reference the variable that contained the formula.
I will post my solution shortly once i have the code finalized and debugged.

VBA Error Handling Multiple times

I have an issue. I have values in a workbook that are getting read into an array. The values come from an XML list so sometimes can be numbers or text, and if they are numbers in text format ("1" for example), they need to be converted to number format, so I multiply them by 1. If the value is text "LS" for example, I am trying to use an error handler to keep the value as "LS".
I have developed the code below: It works once, but the next time I use a similar method (with 'Dummy2') the code it produces a 'Type Mismatch' error.
On Error GoTo Dummy1
For i = 1 To nrows1 - 1
If (Worksheets("Import").Cells(i + 1, 26) * 1 = "") Then
Dummy1:
Table1(i, 1) = Worksheets("Import").Cells(i + 1, 26)
Else
Table1(i, 1) = Worksheets("Import").Cells(i + 1, 26) * 1
End If
Next
On Error GoTo 0
I also tried Clearing Err after the above code with no success.
Please help!
You can use the IsNumeric function:
Sub test3()
Dim Test As Variant
Dim i As Long
For i = 1 To nrows1 - 1
Test = Worksheets("Import").Cells(i + 1, 26)
If IsNumeric(Test) Then
Table1(i, 1) = Test * 1
Else
Table1(i, 1) = Test
End If
Next
End Sub
use VAL(Worksheets("Import").Cells(i + 1, 26)) to determine if it is a Number or not. VAL will give you 0 for "LS".
You could try TryParse functions - but not sure if its available in your version of VBA

Lcase operation on array taking too long

I'm working with a script designed to compare values returned from a form against values from a database dumped to an array, via GetRows. The purpose of the check is to compare form values against database values and only update the matching ids' rows in the database.
I've seen this done with hidden variables in forms, but as we have quite a few users online at any given time, the values on the db end could change while a user was completing the form.
Currently, the code uses an inner and outer loop to run this comparison, with a temporary variable being assigned the current col/row from the aforementioned array. An lcase and trim operation are performed on the value to obtain the temporary variable.
This is causing a considerable performance drain, and I was wondering if the lcase/trim functionality could perhaps be performed during the creation of that array, rather than in a looping situation?
Here's my code:
**note: this utilizes the FastString Class for concatenation, thus the "FastString" and ".Append"
dim iRowLoop, iColLoop, zRowLoop, strChange, tempDbValsCase
Set strChange = New FastString
for iRowLoop = 0 to ubound(arrDbVals, 2)
for zRowLoop = 0 to ubound(arrFormComplete)
''#****below line is what is causing the bottleneck, according
''#****to a timer test
tempDbValsCase = lcase(trim(arrDbVals(1, iRowLoop)))
''#****
if (mid(trim(arrFormComplete(zRowLoop)),1,8) = trim(arrDbVals(0, iRowLoop))) AND (mid(trim(arrFormComplete(zRowLoop)),9) <> tempDbValsCase) then
dim strFormAllVals
strFormAllVals = arrFormComplete(zRowLoop)
strChange.Append strFormAllVals & ","
end if
next
next
On the database side (MS SQL Server 2008), the table from which the array is derived through GetRows contains the bit datatype column "Complete". The lcase and trim operations are performed upon this column of the array. Does the bit datatype add any hidden characters in the output? Visually, I don't detect any, but when I compare a value of "True" from the form input against a value from the array that looks like "True," it doesn't match, until I run the lcase and trim on the "Complete" column.
Try
dim iRowLoop, iColLoop, zRowLoop, strChange, tempDbValsCase
dim iCount1, iCount2, match
Set strChange = New FastString
iCount1 = ubound(arrDbVals, 2)
iCount2 = ubound(arrFormComplete)
for iRowLoop = 0 to iCount1
for zRowLoop = 0 to iCount2
' Assign array lookup to a variable '
tempDbValsCase = arrDbVals(1, iRowLoop)
' ...and then perform operations on it one at a time '
tempDbValsCase = trim(tempDbValsCase)
tempDbValsCase = lcase(tempDbValsCase)
' Assign this array lookup to a variable and perform trim on it '
match = trim(arrFormComplete(zRowLoop))
if (mid(match,1,8) = trim(arrDbVals(0, iRowLoop))) AND (mid(match,9) <> tempDbValsCase) then
strChange.Append match & ","
end if
next
next

BULK INSERT with inconsistent number of columns

I am trying to load a large amount data in SQL server from a flat file using BULK INSERT. However, my file has varying number of columns, for instance the first row contains 14 and the second contains 4. That is OK, I just want to make a table with the max number of columns and load the file into it with NULLs for the missing columns. I can play with it from that point. But it seems that SQL Server, when reaching the end of the line and having more columns to fill for that same row in the destination table, just moves on to the next line and attempts to put the data on that line to the wrong column of the table.
Is there a way to get the behavior that I am looking for? Is there an option that I can use to specify this? Has anyone run into this before?
Here is the code
BULK INSERT #t
FROM '<path to file>'
WITH
(
DATAFILETYPE = 'char',
KEEPNULLS,
FIELDTERMINATOR = '#'
)
BULK INSERT isn't particularly flexible. One work-around is to load each row of data into an interim table that contains a single big varchar column. Once loaded, you then parse each row using your own routines.
My workaround (tested in T-SQL):
Create table with colum count = minimum column count of your import file
Run bulk insert (it will succeed now)
In last table column, you will find all rest items (including your item separator)
If it is necessery for you, create another full-columned table, copy all columns from first table, and do some parsing only over last column.
Example file
alpha , beta , gamma
one , two , three , four
will look like this in your table:
c1 | c2 | c3
"alpha" | "beta" | "gamma"
"one" | "two" | "three , four"
Another workaround is to preprocess the file. It may be easier to write a small standalone program to add terminators to each line so it can be BULK loaded properly than to parse the lines using T-SQL.
Here's one example in VB6/VBA. It's certainly not as fast as the SQL Server bulk insert, but it just preprocessed 91000 rows in 10 seconds.
Sub ColumnDelimiterPad(FileName As String, OutputFileName As String, ColumnCount As Long, ColumnDelimiter As String, RowDelimiter As String)
Dim FileNum As Long
Dim FileData As String
FileNum = FreeFile()
Open FileName For Binary Access Read Shared As #FileNum
FileData = Space$(LOF(FileNum))
Debug.Print "Reading File " & FileName & "..."
Get #FileNum, , FileData
Close #FileNum
Dim Patt As VBScript_RegExp_55.RegExp
Dim Matches As VBScript_RegExp_55.MatchCollection
Set Patt = New VBScript_RegExp_55.RegExp
Patt.IgnoreCase = True
Patt.Global = True
Patt.MultiLine = True
Patt.Pattern = "[^" & RowDelimiter & "]+"
Debug.Print "Parsing..."
Set Matches = Patt.Execute(FileData)
Dim FileLines() As String
Dim Pos As Long
Dim MissingDelimiters
ReDim FileLines(Matches.Count - 1)
For Pos = 0 To Matches.Count - 1
If (Pos + 1) Mod 10000 = 0 Then Debug.Print Pos + 1
FileLines(Pos) = Matches(Pos).Value
MissingDelimiters = ColumnCount - 1 - Len(FileLines(Pos)) + Len(Replace(FileLines(Pos), ColumnDelimiter, ""))
If MissingDelimiters > 0 Then FileLines(Pos) = FileLines(Pos) & String(MissingDelimiters, ColumnDelimiter)
Next
If (Pos + 1) Mod 10000 <> 0 Then Debug.Print Pos + 1
If Dir(OutputFileName) <> "" Then Kill OutputFileName
Open OutputFileName For Binary Access Write Lock Read Write As #FileNum
Debug.Print "Writing " & OutputFileName & "..."
Put #FileNum, , Join(FileLines, RowDelimiter)
Close #FileNum
Debug.Print "Done."
End Sub
The varying number of columns means it can't be parsed by the bulk insert code.
How does it know the correct number of columns? What if you supply too many?
You'll have to upload it to a table with 4 columns, and split out the rest later (or one big column)
Or pre-process it to generate an equal number of columns.
Try specifying a ROW terminator along with your field terminator.
BULK INSERT #t
FROM '<path to file>'
WITH
(
DATAFILETYPE = 'char',
KEEPNULLS,
FIELDTERMINATOR = '#',
ROWTERMINATOR = '\n' --Or whatever signifies the end of a row in your flatfile.
)
More info on this can be found here:
http://msdn.microsoft.com/en-us/library/ms191485.aspx

Resources