I saw post with similar question but seems it could not answer mine, I apologize upfront if this is a duplicated post, as I think my problem is a bit different from what was being asked in another previous post.
I have created a continuous form where there are 2 textbox, which will do calculation with each other when either one of them are being changed.
One is a "Mark-up" textbox with code of Me.Mark_Up = (Me.Unit_Selling_Price / Me.Cost_Unit_Price) - 1
Another textbox is a "Unit Selling Price" textbox with code of Me.Unit_Selling_Price = (Me.EUR_Cost_Unit_Price) * (1 + Me.Mark_Up). Each code was being put under as the After Update event, triggering the calculation if the other textbox has been changed.
Then I added a "Round-up" button which will execute the update query which then will roundup the number in the "Unit Selling Price" textbox. I tried 2 ways to update the "Mark-up" textbox but neither way works:
Insert code into update query to update the mark-up textbox as well but turns out all calculation done are inaccurate (examples as below):
Insert code of Me.Mark_Up = (Me.Unit_Selling_Price / Me.Cost_Unit_Price) - 1 after pressing the "Round-up" button and executing the update query, but "Mark-up" textbox did not update accordingly.
How should I code this?
Keep in mind that when you use VBA code to update a control (or a query), then the event stubs (such as after update) do NOT fire.
So, if you going to use code to update the data?
You need to code in the use of the after update code.
There are several ways to do this, but one tip would be to make sure that the after update code is a "stand alone" type of code routine. That way, you can use the SAME code in one place for both operations. (you really don't want to have to maintain two copies of that calculation code - since it THEN becomes rather easy to have those two routines use differnt rounding or slightly different code - thus resulting in DIFFERENT results for what should be the same thing.
So for the several text boxes, and the after update code? You could say set things up this way:
Me.Mark_Up = MyMarkUpCalc(Me.Unit_Selling_Price, Me.Cost_Unit_Price)
And then in the form have this:
Public Function MymarkUpCalc(cSell as currency, cCost as currency) as currency
MymarkUpCalc = (cSell / cCost) - 1
End Function
So now you have a COMMON routine.
Now, in your code that does the "round"
I would suggest this code:
Sub MyRound
if me.dirty = true then me.dirty = false 'save any pending writes
dim rst as DAO.ReocrdSet
set rst = me.RecordSetClone
rst.moveFirst
do While rst.EOF = false
rst.Edit
rst!SomeRoundField = some new value
rst!Unit_Selling_Price = MyMarkUpCalc(rst!Unit_Selling_Price, rst!Unit_CostPrice
rst.Update
rst.MoveNext
loop
So, in place of say a update query (sql), I think a loop + code will work somewhat better, and thus you now have a common set of calculation routines. Even if the routine is wrong, it will be constant wrong!
So now both your after update events, and your round up processing routine(s) will both use the SAME calculation code.
It is hard to tell your issue, as we don't have your secret update code.
Your results seem a bit off, so something is wrong. The correct results (last column) should be:
c c * (1 + m) -Int(-c * (1 + m))
296.53 505.049896 506
2225.69 3790.795208 3791
7074.41 12049.135112 12050
4659.79 7936.554328 7937
For extended rounding methods, study my project VBA.Round.
Related
I'm quite new to Stack Overflow and VBA, so forgive me.
For x = 1 To Rows
For y = 1 To rs.Fields.Count
Select Case rs.Fields(y - 1)
Case rs![begin_date], rs![end_date]
Z = CDate(rs.Fields(y - 1))
Case rs![deadline_date]
If rs![update_date] = "" Or IsNull(rs![update_date]) Then
Z = Calculate_deadline(rs![begin_date], rs![sla], _
rs![special_calendar])
Else
Z = Calculate_deadline(rs![update_date], rs![sla], _
rs![special_calendar])
End If
Case Else
Z = rs.Fields(y - 1)
End Select
table_list_object.HeaderRowRange.Cells(x + 1, y).Value = Z
Next y
rs.MoveNext
Next x
So, in a nutshell, I'm writing a VBA code in Access that executes a Query to gather the data about all the project dates, calculates its deadlines and write all that in an Excel table.
The function part calculates the deadline date.
The problem is, I write every data one by one, like this:
table_list_object.HeaderRowRange.Cells(x + 1, y).Value = z
That might take a while, and I'm pretty sure this does slow down a lot my macro, but every VBA tutorial I saw did like this.
And I'm a little skeptical about the Select Case thing... Is it better that way, or should I use If ... Else instead?
Anyways, this Recordset has 15.000 rows but it's taking hours to execute, and the first times I ran this code it took some minutes, only.
Oh, by the way, the Calculate_deadline also might be the problem, I know. But I wanna be sure about this part of my code first, just to not make this question too big and complex to explain.
Thanks!
Vitor, since you are new to VBA, I'd suggest that you consider another way to do this in Excel. Excel has a "Get Data" function that uses a technology called Power Query to pull data into Excel, manipulate it, and then save the manipulated data into a sheet in your Excel workbook. All of this using a point-and-click interface, rather than writing low-level VBA code.
See the following as an example:
https://www.youtube.com/watch?v=vchsUEHXvZo
This function is fairly easy to learn, and has common data manipulation functions, like filtering data, aggregating data, adding new calculated columns, transposing data, etc.
Just google "Power Query", and surf the videos and other resources out there.
I'm currently learning Access 2016 since i find it works wonders with Excel.
However i'm trying to find the correct SQL code for detecting certain words in Long Text and only output these words not the text itself
Here is the setup
Fieldname: Type
Long Text
Cell Information
Cell1: Johan have a nice car
Cell2: Jane road a bike.
Cell3: Janes bike was red
Output
Cell1: car
Cell2: bike
Cell3: bike
I'm only interested in keeping certain words from these strings when the query is done, and they should be output to the same Fieldname, i have tried to locate this information for the most part of the day and my last hope of sanity was to check in here if someone has an idea of which function i should be using.
Thank you for your time
You will probably have to use VBA for this, depending on how big your list of words is, but one way to do it with SQL, assuming a relatively small and FIXED list of words:
IIF(<Mytext> LIKE '*car*','car',IIF(<Mytext> LIKE '*bike*','bike',''))
You could either read the values from a table or fill an array. Both would work, but I prefer table-driven code because, for something like this, adding new search terms would only require you to add them to your table.
So, what I would do is first create a new table called tblSearchTerms. In that table, create one field called SearchTerms, and put each of your terms (i.e. "Car", "Bike", etc...) in there, one per record.
Then set up a function in Access. Open a Module (either a new one or one you already have, as long as it's a Module), and enter this:
Function SearchExists(sString As String) As String
Dim db as Database
Dim rec as Recordset
Set db = CurrentDB
Set rec = db.OpenRecordset("Select SearchTerms from tblSearchTerms")
Do while rec.EOF = False
If InStr(1, sString, rec(0)) > 0 Then
SearchExists = "" & rec(0) & ""
Goto BugOut
Else
End If
Loop
SearchExists = "Not Found"
BugOut:
End Function
Now, what you do is create a query. In that query, you'll have one field to check to see if your search term exists. It will look something like this:
MySearchTerm: SearchExists([Cell1])
When you run your query, that field will either populate with one of the search terms (if it's found), or will return "Not Found".
This may require a bit of tweaking, because it's more for finding a search term in an Access table, so there's going to need to be some adjusting to make it work with Excel, but it's pretty close to what you need.
The 1,500 page Access 97 Bible (don't laugh!) that I've been given by my boss to solve his problem doesn't solve my problem of how to solve his problem, because it has nee VBA code.
Let me first make clear that I've made attempts to solve this without (much) coding, and that I've coded quite a bit in VBA already, so I'm basically familiar with most things including recordsets, queries, etc etc but have problems with MS Access limits on how to form a report with data coming from VBA variables. I'm also versatile in most programming languages, but this is not a language problem but rather a "how to/what's possible" problem.
My problem right now is that dragging the query fields into the Detail subform and putting them into cells in columns setting Left and Top with VBA code are moving them alright, but each cell is on a new page. Unfortunately, there is multiple data in each cell that won't conform to the Create Report Guide options available.
So my question is simply this: Can someone point me to working examples of code that create, place, and fill with VBA variable strings, text fields at any coordinate I please on a paper size of my choice?
Edit: The above is not an option, as I understand this will prohibit the client from getting an .mde database. What remains, then, is to merely ask for some sound advice on how to get several rows GROUPed BY weekday and machine (see below) into a recordset or similar for each cell. I guess the best way is to count the number of columns in the table (machines in the sql result) and create 5 rows of these with dummy data, then go through the result rows and place the data in the relevant controls. But if you have ideas for doing this work better and faster, write them as answers.
Sorry for this, I knew there was something I wasn't understanding. Basically, I thought Access supported creating reports dynamically via VBA, ie. "generating pages with data" rather than "preparing a flow of controls connected to datasources". But Access requires that you create an ample amount of dummy, unlinked controls manually, then either fill or hide them and that's how they become "dynamic".
This is for Access 2003 on a remote server accessing local and remote ODBC SQL database tables, if relevant. The goal is to make a week schedule of n columns (n=number of machines at a certain plant) x 5 rows (weekday Mon-Fri), and put 1 or more recordset rows (=scheduled activities for that day on that machine) in each of the "n by 5 table" cells.
If you detect venting frustration in this post I can only ask your forgiveness and hope for your understanding.
So, has many techniques for this:
Ex: 1) using dinamic sql for this:
'Create a function to make sql query
Function MakeMySQlReport(Parameters):
Dim strSql as string
Dim strMyVar as string
strsql = vbnullstring
strsql = "Select " & myVar1 & " as MyFieldVar1, * from myTable where Fieldx =" & Parameters
MyReport.recordSource = ssql
End Function
Ex: 2) create function that returns yours strings:
Function MyString1() as string
MyString1 = 'ABC'
end Function
An in your report, select the textbox will receive the value and type =MyString1()]
I hope this help to you, need more examples?
Solution:
Create many objects manually (grr!)
name them systematically
put them in a Control Array (get all Me.Controls, sift out the ones you're interested in, and put them in an indexed array)
go through the array and change their properties
Sorry but I'm not very experienced when it comes to things like this.
I have a table called "Measure Table" with the fields "ID", "Proxy" and "ProxyID".
I created a form based on this table. ID is a label pre-populated from the table. Proxy is a drop down menu with the options "For" or "From". ProxyID contains a drop down with the same numbers as ID.
I would like a user to go to a specific record in the form (say for ID:I800), select "For" from the Proxy drop down and then select ProxyID (lets say L800). For the record for L800, I want it to automatically change the proxy to "From" and the ProxyID to I800.
Is this possible in Access?
Thanks so much for any help provided
Here is a visual of what i wnat to happen:
I want the table to look like this before the update(when the user selects "For" and "L800"):
Record# ID Proxy ProxyID
1 I800 For L800
2 L800
Then the table is automaticaly updated to:
Record# ID Proxy ProxyID
1 I800 For L800
2 L800 From I800
Okay, here is the gist of what you need to do to solve your immediate problem (updating the corresponding row in the other table.
Simply add an event handler to the AfterUpdate event of the form to perform the update to the other row. The code should look very similar to this...
Private Sub Form_AfterUpdate()
Dim RelatedID As String
Dim Proxy As String
If (UCase(Me.Form!Proxy) = "FOR") Then
RelatedID = Me.Form!ProxyID
CurrentID = Me.Form!ID
DoCmd.RunSQL ("UPDATE [Measure Table] SET ProxyID='" & CurrentID & "', Proxy='From' WHERE ID='" & RelatedID & "'")
End If
End Sub
Caveats:
As I mentioned in the comments, this data structure is a very bad idea and will create a lot of extra work for you to maintain the data integrity according to the implicit rules you are specifying as a matter of course with this design. I realize you have an existing DB to deal with, but frankly it would probably be less work to fix the DB design than maintain this one in the long run.
Some additional considerations you didn't ask about, but are going to need to deal with:
What happens if someone updates
either of the entries in a pair
directly in the table instead of
using your form? There really isn't a
good way to apply the above logic to run when
except in the context of using the form.
What happens in this code if the related row doesn't exist for some reason?
What happens if the related row "The FROM" row is updated in the form?
What happens if either row is deleted from the table?
I want to display a "Please Wait" form while a 60+ second query is running. I have the query and the form made (easy enough), except the macro won't bring them together. Here is my autoexec macro:
SetWarnings=False
Open Wait Form
Run the query & Display Results
Close Wait Form
The problem is that I can only see the outline of my wait form while the maketable query is running. I can only guess that the macro doesn't wait for the form to completely load before going to the next step.
And just for fun:
The Wait form has a Timer that shows the number of seconds elapsed. How do I run the query while still allowing the form to update itself at the same time?
-------Update----------
Repaint only updates the background color before moving on to the query. I also tried 6 repaints in a row with no difference (I thought that might get around the bug you people mentioned). The form is very simple. A single text box that uses "loading" for the control source and a timer function (disabled for the moment). Here is my macro in slightly greater detail:
SetWarnings=False
Open Wait Form (modal=yes, popup=no)
Repaint the form
Open a maketable query (this query saves alot of time)
Close Wait Form
Open the display query
Firstly, you just need to Repaint the wait form after it is shown for it to show correctly, it's just a bug in VBA that sometimes causes forms not to be displayed properly even if they are drawn at the correct point in the code.
Secondly, if you set the wait form's ShowModal property to false then you will be able to update it through your routine. I use a public function that takes a 0-100 argument to update a progress bar. This works best in a loop where you can normally calculate the number of loops remaining and provide an accurate guide to the elapsed progress, but even when performing a series of operations you can time and pass suitable values through to the progress form so that the user is kept informed. This works better than most Windows progress bars!
The first problem is easy to solve, try putting me.Repaint before the query runs, sometimes access can get a bit lazy with screen painting and you have to force it.
As for the other thing that is a bit more complicated. You would have to execute the query asynchronously. You can do this in ADO by adding the adAsyncExecute option when executing the query. You would then catch the finishing event to tell the users the query is done
Here is a link on the Microsoft knowledge base http://support.microsoft.com/kb/262311
If you are using an Action Query you can track the number of executed rows by using a vba-function which returns the same value that was passed to it. Of course you have to know the total number of rows, to know when the query is done or display progress (This can often be achieved relatively fast using a lightweight counting query*).
'first some global vars to keep track of the number
Dim lngCurrentRow as Long
Dim lngTotalRows as Long 'We assume lngTotalRows have been set elsewhere
'Here is the function
Public Function UpdateProgress(FieldValue as Variant) as Variant
lngCurrentRow = Nz(lngCurrentRow, 0)
If (lngCurrentRow >= lngTotalRows) then
MsgBox "Query Done!"
Else
'Do stuff to show progress
End If
lngCurrentRow = lngCurrentRow + 1
End Function
For displaying the progress I have used an Unbound form, with an empty textfield with transparent background (progressFrame) and a label (progressLabel) which has a blue background and is placed behind the textbox to the left. For each call to UpdateProgress you can then set the width of the label:
progressLabel.Width = progressFrame.Width * (lngCurrentRow / lngTotalRows)
*: F.ex. if the query is based on one table, with some added data, so that the number of records the query will produce is equal to that of the table, a count can be done on the table alone so that it will be faster..
I hope this was helpful, or at least inspiring :)
I had the same issue with a pop up form which took a few seconds before it displayed the text which informs the user that something is processing so please wait. I added the line of code below after the code which opens the form and before the next bit of code which runs the update queries (which takes a while hence the need to inform the user that something was processing)
DoCmd.RepaintObject acForm, "frmMyForm"
Works perfectly for me.