Currently I'm attempting to determine how to easily be able to enter data either in Excel or Access. I'd use the Data form tool in excel however I'm using a scanner that's configured to send an enter command after a successful scan so it would move to the next cell.
Serial Number Employee Time
123 Brian 8/20/13 8:49:21 PM
213 Brian 8/20/13 8:49:21 PM
334 Nick 8/20/13 8:49:21 PM
I'd like to be able to have an accurate time that the serial number was scanned. As it is right now every time a change was made on the sheet the time updates which really defeats the purpose. I'm currently using this formula:
=IF(A2<>"",NOW(),"")
I'd also like to be able to make the employee name able to be changed but also stay the same during the time when that person is scanning the items. I tried just referencing a dropdown list but, when that field changes so does the rest of the employee field.
I'm guessing that this would be best suited for Access because eventually this will be located in different locations and I'd need to be able to correlate the data.Honestly, I'm just too unfamiliar with it to be able to really create something amazing and have it work.
Any help would be GREATLY appreciated.
Because your serial numbers most likely correlate to some articles and you already think of multiple locations and users, I would suggest using Access.
All this leans more to a datebase, which might not be that intuitive to set up for you as excel would be, but in the end it is way more solid and easier to handle, when it comes to catching dublicates, and making queries.
However, it can be done both ways. But not using now() - because this function would update your time, whenever recalculated. That is why you get the same time over and over.
You would have to create and call a function, which inserts the time as fixed text, not as dynamic content.
On Access however, using a now-function as the default value for a field would work, as the database-entry would be the value not the function.
For Excel you would have to ramp up this function and could create/activate a keylistener, when activating a new Worker:
'This code goes into a VBA-Module
'and can be access on a Worksheet calling =myScan("test")
Public Function myScan(strWorker As String)
Table1.Cells(2, 1) = "1"
Table1.Cells(2, 2) = strWorker
Table1.Cells(2, 3) = Now()
End Function
The Serial-Number can be derived from the row. The main Problem would be to stay on the current/next row to paste the data in.
But you could - just for instance - create an Excel Dialog to select a Worker, then activate a Scan mode and scan ... you could even connect to a Web or Access database, not storing the data in excel, which I would highly recommend ;)
Edit
'This code works, when you place it as the VBA-Code of your worksheet
Private Sub Worksheet_Change(ByVal Target As Range)
'react only on changes on column A
If (Target.Column = 1) Then
'react only on changes on column A when the row is greater than 5
If (Target.Row > 5) Then
'use the current time for Bx
Me.Cells(Target.Row, 2) = Now()
'use the user-name from C2 in Cx
Me.Cells(Target.Row, 3) = Me.Cells(2, 3)
End If
End If
End Sub
Use ALT+F11 open the VBA-Editor and choose the table-object you want to use and place the code above into it, than save as a Macro-Excel-Dokument.
Your worksheet should look like this:
It will automatically update, whenever you change something from A6-Ax.
The short answer is; Excel is NOT a database. If you're going to be reporting on data, and it's going to contain a LOT of data, don't even consider Excel. It's a SPREADSHEET, not a DATABASE.
Related
I have a table including start time & end time fields. I want to insert the start time, that should be automatically appears when I type something in a row. And I want to insert end time, that also should be automatically appears when i go to the next row.
I have entered as time() in default value from the design view. But I get start time & end time as same. That is not right. What is the correct method to fix this.
Can any one help to me?
Wayne is right as long as you are entering information directly into the table, I do not believe there is anything you can do to record the end time. If you want to use a form this would be possible. Forms are generally better for data entry anyway.
The event you would probably want to use would be "After Update" (ie. After one of the fields change) you could either use the code after the last field (ie. only show end time when the last field is entered or changed) or for every field (this will give the last time any field was updated regardless of order)
The code would look like this (with your actual fields):
Private Sub Field_Name_AfterUpdate()
Me![end time] = Now()
End Sub
You can find the events from the design view click on the field and open the property sheet then go to the event tab and click on the "..." the go to code builder and you would just add the line of code in the middle (make sure the field name matches exactly) (it will automatically add the first and last line)
===========================================
Edit:
Ok so three main things are stopping you right now. I know this can be really difficult when you start, but as soon as you get it to work it will feel amazing.
First - you do NOT want to place the code under starttijd because that field just starts with the default value and never changes. Thus putting code on the Before update or After update will not run. You need to place this in the fields that are updated (ie the fields people fill out with the form) So if they fill out a name for example then you would place the code there
Second - The code is meant to update the END time not the start time ie Me![END]=Now() not Me![starttijd]=Now()
Third - The code you will want to run on After update not before update. Though this is not as important as the above two
I am working on my first SSIS package. I have a view with data that looks something like:
Loc Data
1 asd
1 qwe
2 zxc
3 jkl
And I need all of the rows to go to different files based on the Loc value. So all of the data rows where Loc = 1 should end up in the file named Loc1.txt, and the same for each other Loc.
It seems like this can be accomplished with a conditional split to flat file, but that would require a destination for each Location. I have a lot of Locations, and they all will be handled the same way other than being split in to different files.
Is there a built in way to do this without creating a bunch of destination components? Or can I at least use the script component to act as a way?
You should be able to set an expression using a variable. Define your path up to the directory and then set the variable equal to that column.
You'll need an Execute SQL task to return a Single Row result set, and loop that in a container for every row in your original result set.
I don't have access at the moment to post screenshots, but this link should help outline the steps.
So when your package runs the expression will look like:
'C:\Documents\MyPath\location' + #User::LocationColumn + '.txt'
It should end up feeding your directory with files according to location.
Set the User::LocationColumn equal to the Location Column in your result set. Write your result set to group by Location, so all your records write to a single file per Location.
I spent some time try to complete this task using the method #Phoenix suggest, but stumbled upon this video along the way.
I ended up going with the method shown in the video. I was hoping I wouldn't have to separate it in to multiple select statements for each location and an extra one to grab the distinct locations, but I thought the SSIS implementation in the video was much cleaner than the alternative.
Change the connection manager's connection string, in which you have to use variable which should be changed.
By varying the variable, destination file also changes
and connection string is :
'C:\Documents\ABC\Files\' + #User::data + '.txt'
vote this if it helps you
My report gets data from SQL based on a date range, uses custom code to calculate totals by Employee and CategoryType and stores the values in a dictionary. To get the grand total by Employee, in a matrix cell, I call a function and pass it the EmployeeID which returns the accumulated total. A chart is populated with data the exact same way.
Everything works as it should when running the report directly in Report Builder 3.0. However, problems arise when exporting the report to Excel. The first time it's exported, the totals are doubled. Each consecutive time, the multiplier is incremented by one. (1st - doubled; 2nd - tripled; 3rd - quadrupled, etc.). To work around this problem, I override the Init event and clear the dictionary variable (see below for code--notice I'm using the keyword Shared which I found out about on another posted question). Problem solved for Excel as now the dictionary is garbage collected and it will not recalculate from what already exists in memory.
But now a different problem exists. When executing the report via the Web, the matrix populates with data and the totals are correct although the chart only populates with data within a week date range from the current date. Very strange! If I increase the date range to longer than a week, I get a blank chart. The link above implies this may be due to the "report on demand" engine of SSRS but offers no solution to the problem in my mind. I need a solution that will work (showing correct totals and populating chart with data) when exporting the report to Excel and when simply viewing on the Web. I will post screenshots and more info if needed.
I've tried overriding the LoadComplete event (thinking this would be a great time to clear the dictionary as all other controls on page are loaded), but not sure this is possible in SSRS custom code and unsure of the proper syntax.
Is there a different render event I should be using instead to make this work? Anyone ever run across something similar and have a reasonable solution?
public Shared Dim dict As New System.Collections.Generic.Dictionary(Of String, Decimal)
'Override built-in OnInit function and clears dictionary; ensures correct totals when exporting to Excel
Protected Overrides Sub OnInit()
dict.Clear()
End Sub
I have a database formatting problem in which I am trying to concatenate column "B" rows based on column "A" rows. Like So:
https://docs.google.com/spreadsheet/ccc?key=0Am8J-Fv99YModE5Va3hLSFdnU0RibmQwNVFNelJCWHc
Sorry I couldn't post a picture. I don't have enough reputation points YET. I'LL Get them eventually though
So I'd like to solve this problem within Excel or Access. Its currently an access database, but I can export it to excel easily. As you can see, I want to find "userid" in column A and where there are multiple column A's such as "shawn" I'd like to combine the multiple instances of shawn and concatenate property num as such.
Even though there are multiple instances of column A still, I could just filter all unique instances of the table later. My concern is how to concatenate column B with a "|" in the middle if column A has multiple instances.
This is just a segment of my data (There is a lot more), so I would be very thankful for your help.
The pseudo code in my head so far is:
If( Column A has more than one instance)
Then Concatenate(Column B with "#"+ "|" +"#")
I'm also wondering if there is a way to do this on access with grouping.
Well Anyways, PLEASE HELP.
In excel we can achieve it easily by custom function in vba module. Hopefully using vba(Macros) is not an issue for you.
Here is the code for the function which can be added in vba. (Press Alt+F11, this will take you to visual editor, right click the project and add a module. Add the below code in module)
Public Function ConcatenatePipe(ByVal lst As Range, ByVal values As Range, ByVal name As Range) As String
ConcatenatePipe = ""
Dim i As Integer
For i = 1 To lst.Count
If name.Value = lst.Item(i).Value Then ConcatenatePipe = ConcatenatePipe & "|" & values.Item(i).Value
Next
ConcatenatePipe = Mid(ConcatenatePipe, 2)
End Function
This function you can use in excel in F Column of your example. Copy the below formulla in F2 and the copy paste the cell to rest of F column. =ConcatenatePipe($A$2:$A$20,$B$2:$B$20,E2)
I believe you can solve this with an SQL GROUP BY function. At least, here's how I'd do it in MySQL or similar:
SELECT userid, GROUP_CONCAT(propertynum SEPARATOR '|') FROM Names GROUP BY userid
as described in this stack overflow post: How to use GROUP BY to concatenate strings in MySQL?
Here's a link on how to use SQL in MS Access: http://www.igetit.net/newsletters/Y03_10/SQLInAccess.aspx
Unfortunately there is not a GROUP_CONCAT function in MSAccess, but this other SO post explains some ways round that: is there a group_concat function in ms-access?
I am copying a record from one table to another in Access 2007. I iterate through each field in the current record and copy that value to the new table. It works fine until I get to my lookup column field that allows multiple values. The name of the lookup column is "Favorite Sports" and the user can select multiple values from a dropdown list.
I believe the values of a multivalued field are stored in an array but I cannot access the values in VBA code! I've tried myRecordset.Fields("myFieldName").Value(index) but it didn't work. I don't understand how Access stores multiple values in one field.
I saw something about ItemsSelected on another forum but I don't know what Object is associated with that method.
Thanks for any help!
I would recommend against using multivalue fields for precisely the reason you're running into, because it's extremely complex to refer to the data stored in this simple-to-use UI element (and it's for UI that it's made available, even though it's created in the table design).
From your mention of "ItemsSelected," you seem to be assuming that you access the data in a multivalue field the same way you would in a multiselect listbox on a form. This is not correct. Instead, you have to work with it via a DAO recordset. The documentation for working with multivalue fiels explains how to do it in code, something like this:
Dim rsMyField As DAO.Recordset
Set rsMyField = Me.Recordset("MyField").Value
rsChild.MoveFirst
Do Until rsChild.EOF
Debug.Print rsChild!Value.Value
rsChild.MoveNext
Loop
rsChild.Close
Set rsChild = Nothing
Now, given that you can usually access the properties of a recordset object through its default collections, you'd expect that Me.Recordset("MyField").Value would be returning a recordset object that is navigable through the default collection of a recordset, which is the fields collection. You'd think you could do this:
Me.Recordset("MyField").Value!Value.Value
This should work because the recordset returned is a one-column recordset with the column name "Value" and you'd be asking for the value of that column.
There are two problems with this:
it doesn't actually work. This means that Me.Recordset("MyField").Value is not reallly a full-fledged recordset object the way, say, CurrentDB.OpenRecordset("MyTable") would be. This is demonstrable by trying to return the Recordcount of this recordset:
Me.Recordset("MyField").Value.Recordcount
That causes an error, so that means that what's being returned is not really a standard recordset object.
even if it did work, you'd have no way to navigate the collection of records -- all you'd ever be able to get would be the data from the first selected value in your multivalued field. This is because there is no way in this shortcut one-line form to navigate to a particular record in any recordset that you're referring to in that fashion. A recordset is not like a listbox where you can access both rows and columns, with .ItemData(0).Column(1), which would return the 2nd column of the first row of the listbox.
So, the only way to do this is via navigating the child DAO recordset, as in the code sample above (modelled on that in the cited MSDN article).
Now, you could easily write a wrapper function to deal with this. Something like this seems to work:
Public Function ReturnMVByIndex(ctl As Control, intIndex As Integer) As Variant
Dim rsValues As DAO.Recordset
Dim lngCount As Long
Dim intRecord As Integer
Set rsValues = ctl.Parent.Recordset(ctl.ControlSource).Value
rsValues.MoveLast
lngCount = rsValues.RecordCount
If intIndex > lngCount - 1 Then
MsgBox "The requested index exceeds the number of selected values."
GoTo exitRoutine
End If
rsValues.MoveFirst
Do Until rsValues.EOF
If intRecord = intIndex Then
ReturnMVByIndex = rsValues(0).Value
Exit Do
End If
intRecord = intRecord + 1
rsValues.MoveNext
Loop
exitRoutine:
rsValues.Close
Set rsValues = Nothing
Exit Function
End Function
Using that model, you could also write code to concatenate the values into a list, or return the count of values (so you could call that first in order to avoid the error message when your index exceeded the number of values).
As cool as all of this is, and as nice as the UI that's presented happens to be (it would be really nice if they'd added selection checkboxes as a type for a multiselect listbox), I'd still recommend against using it precisely because it's so much trouble to work with. This just takes the problem of the standard lookup field (see The Evils of Lookup Fields in Tables) and makes things even worse. Requiring DAO code to get values out of these fields is a pretty severe hurdle to overcome with a UI element that is supposed to make things easier for power users, seems to me.
For a quick and dirty way of getting the values out of a multivalued ('complex data') column, you can use an ADO Connection with the Jet OLEDB:Support Complex Data connection property set to False e.g. the connection string should look something like this:
Provider=Microsoft.ACE.OLEDB.12.0;
Data Source=C:\dbs\TestANSI92.accdb;
Jet OLEDB:Engine Type=6;
Jet OLEDB:Support Complex Data=False
The multivaled type column will now be of type MEMO (adLongVarWChar) with each value separated by a semicolon ; character.
But that's only half the problem. How to get data into a multivalued column?
The Access Team seem to have neglected to enhance the Access Database Engine SQL syntax to accommodate multivalued types. The 'semicolon delimiter' trick doesn't work in reverse e.g.
INSERT INTO TestComplexData (ID, weekday_names_multivalued)
VALUES (5, 'Tue;Thu;Sat');
fails with the error, "Cannot perform this operation", ditto when trying to update via ADO recordset :(