Find minimum value of a series in a chart - vba

I have a line chart in a sub-form that is loaded into a variety of reports, the chart has 7 series. I have been trying to alter the 'Y' axis minimum value on load, based on the minimum value of all the series but have been unable to find a way to access the series values. I am able to alter the minimum value by entering a value such as 'Me.LineChart.Axes(xlValue).MinimumScale = 30' but I need to change the value dynamically.
Any pointers on how to get to the values in the data series would be very much appreciated.

Open a recordset of an aggregate query that pulls Min and Max values for filtered dataset then reference fields of recordset.
Set rs = CurrentDb.OpenRecordset("SELECT LabNum, First(Blows) As B, Min(A) AS MinOfA, Min(W) AS MinOfW, Min(S) AS MinOfS, Min(F) AS MinOfF, Min(VMA) AS MinOfVMA, " & _
"Min(VTM) AS MinOfVTM, Min(VF) AS MinOfVF, Max(A) AS MaxOfA, Max(W) AS MaxOfW, Max(S) AS MaxOfS, Max(F) AS MaxOfF, " & _
"Max(VMA) AS MaxOfVMA, Max(VTM) AS MaxOfVTM, Max(VF) AS MaxOfVF FROM GraphBMD WHERE LabNum='" & strLabNum & "' GROUP BY LabNum;")
Or use DMin() domain aggregate function if need only one value.
intMinD = Nz(Int(DMin("D", "GraphProctor", "Source='Lab' AND LabNum='" & strLabNum & "'")), 0)

Related

How do I compare values from one datetime index to a range of other other datetime indexes?

I am using pandas and mplfinance to work with a stock market data set. How can I compare the current index to the previous(x) indexes?
For example I want to find a divergence between the current price and an indicator I am using. (Divergence is when the price is moving lower than the lowest value ‘x’ periods ago and the indicator sharing the same xaxis is not lower than the lowest value ‘x’ periods ago. X being a range of period, in this case a range of datetime indexes).
In order to do that I need to look backwards at the prior data to see if the current value of price is lower than the lowest value in the previous 15 periods. If true, I would need to check if the current value in the indicator is higher than the lowest value in the previous 15 days.
I can write a long hand version of this but it’s really not efficient to rewrite it if I want to use a different time frame or indicator.
This is the long form I managed to slap together:
df[‘bullDiverg’] = np.where( df.close <
((df.close.shift(1) & df.close.shift(2) & df.close.shift(3) & df.close.shift(4) & df.close.shift(5) & df.close.shift(6) &
df.close.shift(7) & df.close.shift(8) & df.close.shift(9) & df.close.shift(10) & df.close.shift(11) & df.close.shift(12) & df.close.shift(13) & df.close.shift(14) & df.close.shift(15))
&
(df.macd.shift >
(df.macd.shift(1) & df.macd.shift(2) & df.macd.shift(3) & df.macd.shift(4) & df.macd.shift(5) & df.macd.shift(6) &
df.macd.shift(7) & df.macd.shift(8) & df.macd.shift(9) & df.macd.shift(10) & df.macd.shift(11) & df.macd.shift(12) & df.macd.shift(13) & df.macd.shift(14) & df.macd.shift(15))),1,0 )
A function where I enter the Datetime df price and indicator Values that creates the bullish divergences Col so I can add it to my existing data would be ideal but just a more efficient way to write what I did above would be appreciated.

Changing headers display and order from a recordset to excel sheet

I have an excel sheet that I use as database, and a search form that allow user to search for information, based on some criterias, and display the filtered results in a new sheet.
I am using SQL to fetch data, and display them to the user.
I use something like top open connection, then to create a record set and pass my sql request to it
m_Connection.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=Yes;"";"
Set OpenRecordset = CreateObject("ADODB.Recordset")
OpenRecordset.Open sql, GetConnection(), 3, 3, &H1
Set rst = OpenRecordset("SELECT * FROM [Database$] Where " & Myconditions & ";")
Everything works fine, but I need to allow users to choose the column headers names and order that may be different from what i have in the sheet from which i make my select that i call database
We need this because users are in different countries, so the display name will be configured based on the country of the user, but also we want to allow user to change the display name and order of the fields based on their needs and because the display name may be too long (multi line).
My real "database" sheet is about 110 columns, and about 1000 records (rows).
I can't publish the real data because it's confidential, but to help you understand me, I created this example that represent what I have
let us suppose I have this "database"
the user enter this search screen to select the information he needs from the database
I wish that the user will get this result and not in the same order and display of the database
as you can see, the display names and orders of the columns in the result page is different from the "database" sheet
I would like to create a configuration page, in which the user can specify the display name he wants and the order in which he wants the fields to appears. something like that
Is there any fast way to do that directly in my Recordset in SQL/EXCEL or I should after I fetch data, change the headers in excel sheet using vba ? if so, I have to make a kind of array in vba that contains both database Names and display names and replace the names of the database by its corresponding just before I show the result page shows ?
any suggestions ?
same question about the order of the fields, how to sort them based on the order the user choosed ? any fast way ?
Thanks for anyone who can help with the best way to do that
You could do the following, it loops through the data range based on the number of rows in the range being the min and max of positions available, it looks for these rankings in turn, in column C, then checks if shown, then add's the field name and it's alias to an array. This array is then joined. So using data similar to yours, in columns of the the same ordering, I called:
GenerateOrderedSQL("table 1",range("a2:d6"),3,4) A1:D1 contained headers
This called my function
Function GenerateOrderedSQL(strInputTable As String, _
rngRangeForSelection As Excel.Range, _
lngOrderColumn As Long, _
lngShowColumn As Long) As String
Dim l As Long
Dim fPos As Long
Dim lfPos As Long
Dim a() As Variant
l = rngRangeForSelection.Rows.Count
ReDim a(l)
For fPos = 1 To l
lfPos = Application.WorksheetFunction.Match(fPos, _
rngRangeForSelection.Columns(lngOrderColumn), 0)
If rngRangeForSelection.Cells(lfPos, lngShowColumn).Value = "Yes" Then
a(fPos-1) = "[" & rngRangeForSelection.Cells(lfPos, 1) & _
"] AS [" & rngRangeForSelection.Cells(lfPos, 2) & "]"
a(fPos-1) = a(fPos-1) & IIf(fPos < l, ",", vbNullString)
End If
Next
Debug.Print "SELECT " & Join(a, vbNullString) & " FROM [" & strInputTable; "]"
End Function`
This gave the following
SELECT [Fname] AS [First Name],[Lname] AS [Last Name],[Zip] AS [Zip],[City] AS [City] FROM [table 1]

Error reading time cell in Excel using SQL (VBA)

I have an excel worksheet with 7 tables (each placed in a different sheet) and I built a routine to select through them, consolidating the data in a single sheet.
All tables have an HOUR column and I have two types of select: a full time range, where I select every row in each table, and a part-time range, where I select only the data between 6:00:00 and 23:00:00.
For i = 2 To Sheets.Count
...
strSQL = "SELECT [APPLICATIONNAME], [DAT], [TRANSACTION_NAME], SUM([TOT]), AVG([PERFORM]), SUM([ERRO]), AVG([TOTAL_TIME]), AVG([PERCENTUAL_AJUSTADO]), [HOUR], LEFT([HORA],2) " & _
" FROM [" & Sheets(ind).Name & "$] " & _
" WHERE (LEFT([HOUR],2) >= 6 AND LEFT([HOUR],2) <= 23)" & _
" GROUP BY [APPLICATIONNAME], [DAT], [HOUR], [TRANSACTION_NAME]" & _
" ORDER BY [DAT], [HOUR], [TRANSACTION_NAME]"
...
Next i
The problem is that it works fine only when I read the first three tables. From the fourth table on, it seems that Excel is converting the time cell to a numeric value and the data becomes incomplete.
I believe it's not a problem of cell formatting, because if I change the order of the sheets, the SELECT continues reading the first three tables perfectly.
I made it print the time read and the LEFT([hour],2). The results for the first three are, for example:
hour = 22:00:00
LEFT([hour],2) = 22
From the fourth table on, the results are (always):
hour = 8,3333333333333
LEFT([hour],2) = 8,
What may be happening? Is there another way to make it work for all sheets?
Thanks in advance.
Ricardo Freire

MS Access multi field search with empty fields or multiple selections from list boxes

can some one kindly help me with MS Access? My problem is similar to the one in the following link:
MS Access multi field search with empty fields
but in my case, each search field is a list box from which we can select multiple things.
In my case, the user of the database application will enter start date and end date (text boxes) which will populate the list boxes (cost center, item number, employee id) from a single database table matching the rows that have effective date falling between start date and end date. After populating the list boxes, the user has the choice to either select multiple cost centers or leave the search field blank, multiple item numbers or blank, multiple employee numbers or blank. After selecting, if the command button display results is pressed, we should be able to get the results which satisfy all these search criteria. For example, if I select cost centers 1301, 1302 and employee no.s 492128, 492690, 492959 and leave the item numbers search field blank, then in the data table, all the entries that match these cost centers and employee no.s (all the search fields are separate columns) which fall between the start date and end date should be displayed.
I am unable to get the logic in VB. Please guide me through.
You'll need to build up an sql statement in vba then run it using a recordset, to get the results back.
Obviously I dont know what the data you'll need to get is, or from the tables you;ll get it from, however the where clause needs to be built as follows:
dim wc as string
wc = wc & iif(lst_costcenter.ItemsSelected.Count = 0, "", " AND " & InClause(lst_costcenter, "tablename.columnname", false))
wc = wc & iif(lst_itemnumber.ItemsSelected.Count = 0, "", " AND " & InClause( ...
Finally when building the sql statement, you'll need to chop of the first "AND" in wc & replace it with "WHERE"
wc = iif(wc <> "", " WHERE " & mid(trim(wc), 5), "")
InClause is a function that you need to add in a module, or in the enquiry form itself:
It uses 3 arguments:
1. The listbox control to build an in clause for,
2. A string comprising tablename-dot-columnname being the table/column to be filtered for the values selected in the listbox, &
3. True/False according to whether the datatype of the column is string (true) or numeric (false)
Public Function InClause(lst as ListBox, tblcol as string, isAlpha as boolean)
Dim si As String
Dim vv As Variant
For Each vv In lstBox.ItemsSelected
If isAlpha Then
si = si & "," & Chr(34) & lstBox.Column(0, vv) & Chr(34)
Else
si = si & "," & lstBox.Column(0, vv)
End If
Next vv
If si <> "" Then
si = "(" & tblcol & " IN (" & mid(si, 2) & "))"
End If
InClause = si
End Function
Hope this helps

Group records into non-contiguous hour-long bins

I have event data of the form, where eventId is a long and time is Date/Time (shown below as just the time for simplicity, since all times will be on the same day):
eventId time
---------------
1 0712
2 0715
3 0801
4 0817
5 0916
6 1214
7 2255
I need to form groups containing an hour's worth of events, where the hour is measured from the first time in that group. Using the above data my groupings would be
Group 1 (0712 to 0811 inclusive): events 1, 2, 3
Group 2 (0817 to 0916 inclusive): events 4, 5
Group 3 (1214 to 1313 inclusive): event 6
Group 4 (2255 to 2354 inclusive): event 7
I've found plenty of examples of grouping data on predefined periods (e.g. every hour, day, 5 minutes) but nothing like what I'm trying to do. I suspect that it's not possible using straight SQL...it seems to be a chicken and egg problem where I need to put data into bins based on the data itself.
The cornerstone of this problem is coming up with the start time of each range but I can't come up with anything beyond the trivial case: the first start time.
The only way I can come up with is to do this programmatically (in VBA), where I SELECT the data into a temporary table and remove rows as I put them into bins. In other words, find the earliest time then grab that and all records within 1 hour of that, removing them from the table. Get the earliest time of the remaining records and repeat until the temp table is empty.
Ideally I'd like a SQL solution but I'm unable to come up with anything close on my own.
Some notes on a possible approach.
Dim rs As DAO.Recordset
Dim db As Database
Dim rsBins As DAO.Recordset
Dim qdf As QueryDef 'Demo
Set db = CurrentDb
'For demonstration, if the code is to be run frequently
'just empty the bins table
db.Execute "DROP TABLE Bins"
db.Execute "CREATE TABLE Bins (ID Counter, Bin1 Datetime, Bin2 Datetime)"
'Get min start times
db.Execute "INSERT INTO bins ( Bin1, Bin2 ) " _
& "SELECT Min([time]) AS Bin1, DateAdd('n',59,Min([time])) AS Bin2 " _
& "FROM events"
Set rsBins = db.OpenRecordset("Bins")
Do While True
Set rs = db.OpenRecordset("SELECT Min([time]) AS Bin1, " _
& "DateAdd('n',59,Min([time])) AS Bin2 FROM events " _
& "WHERE [time] > (SELECT Max(Bin2) FROM Bins)")
If IsNull(rs!Bin1) Then
Exit Do
Else
rsBins.AddNew
rsBins!Bin1 = rs!Bin1
rsBins!bin2 = rs!bin2
rsBins.Update
End If
Loop
''Demonstration of final query.
''This will only run once and then error becaue the query exists, but that is
''all you need after that, just open the now existing binned query
sSQL = "SELECT events.Time, bins.ID, bins.Bin1, bins.Bin2 " _
& "FROM events, bins " _
& "GROUP BY events.Time, bins.ID, bins.Bin1, bins.Bin2 " _
& "HAVING (((events.Time) Between [bin1] And [bin2]));"
Set qdf = db.CreateQueryDef("Binned", sSQL)
DoCmd.OpenQuery qdf.Name