qlikview How to get sheet name - vbscript

I am trying to get all the object details using below code from an application i.e. Name and Id.
Sub Objects
Shtobj = ActiveDocument.ActiveSheet.GetSheetObjects
For i = LBound(Shtobj) To UBound(Shtobj)
'MsgBox(Shtobj(i).GetObjectName)
MsgBox(Shtobj(i).GetObjectId)
Next
End Sub
But the .GetObjectName is not giving the me the name of the object.

Related

No row can be added to a DataGridView control that does not have columns. Columns must be added first. in VB.net

I have been encountering an error in my VB.Net code that says "No row can be added to a DataGridView control that does not have columns. Columns must be added first.". When I was trying to code a live search on a datagridview1. Please help me.
Here is the code for the datagrid live search that encounters an error:
Private Sub txt_search_TextChanged(sender As Object, e As EventArgs) Handles txt_search.TextChanged
DataGridView1.Rows.Clear()
'' Searching via room number or category id, ie room type
Try
conn.Open()
Dim cmd As New MySqlCommand("SELECT r.id, r.room_no, c.name, r.description, r.price FROM categories c JOIN rooms r ON c.id = r.category_id WHERE room_no LIKE '%" & txt_search.Text & "%' or name LIKE '%" & txt_search.Text & "%'", conn)
dr = cmd.ExecuteReader
While dr.Read
DataGridView1.Rows.Add(dr.Item("ID"), dr.Item("room_no"), dr.Item("name"), dr.Item("description"), dr.Item("price"))
End While
dr.Dispose()
Catch ex As Exception
MsgBox(ex.Message)
End Try
conn.Close()
End Sub
I would do a few things differently.
You should not declare your connection at the class level, instead create a new connection and dispose immediately when done.
Same with the DataRow.
I personally wouldn't like to see results immediately after typing a character in a searchbox. If I have a typo, then want to erase it and fix it, I need to wait for the typo result, then see the fixed result. We'll use a timer to create this delay.
Which brings me to the other issue, which is that you are hitting your database on the UI thread, so add that to the last item, your end user is experiencing a UI freeze while waiting for results with each keypress. We will query off the UI and invoke the update back when done.
Don't put textbox Text directly into a query or you will be opened up to sql injection issues. We will use parameters
(Oh, and I haven't even arrived at your question yet!)
You can simply databind the result to the grid instead of trying to add rows. You can only add rows if the grid has predefined rows with a template for new rows. You can do that but this locks your UI into a particular design so if you want to change the query later, you will also need to fix the UI. Too tightly coupled. We'll use a class to define the data. You will get these if you use an ORM which is vastly superior to using a DataReader, but you don't so I made one.
Let's see...
Private Class Result
Public Sub New(iD As Integer, room_no As String, name As String, description As String, price As Decimal)
Me.ID = iD
Me.Room_no = room_no
Me.Name = name
Me.Description = description
Me.Price = price
End Sub
' Update data types according to your actual database types
Public Property ID As Integer
Public Property Room_no As String
Public Property Name As String
Public Property Description As String
Public Property Price As Decimal
End Class
You will want to make a timer to tick when you want to hit the database. Also record the current state of the textbox at this time. This is all you do in the TextChanged event handler
Private queryTimer As New System.Threading.Timer(AddressOf queryCallback)
Private queryTerm As String
Private Sub txt_search_TextChanged(sender As Object, e As EventArgs) Handles txt_search.TextChanged
queryTerm = txt_search.Text.Trim() ' do you want to trim whitespace?
' Execute search 500ms later.
' If multiple keystrokes are pressed quickly,
' previous timer schedules are cancelled and only the last happens.
queryTimer.Change(500, -1)
End Sub
This is the timer callback, which runs off the UI and invokes the UI update when it's done
Private Sub queryCallback(state As Object)
' This routine is called on a background thread, off the UI
Dim results As New List(Of Result)()
Using conn As New MySqlConnection("connection string")
conn.Open()
' build command with parameter
Using cmd As New MySqlCommand(
$"SELECT r.id, r.room_no, c.name, r.description, r.price
FROM categories c
JOIN rooms r ON c.id = r.category_id
WHERE room_no LIKE '%#search%'
or name LIKE '%#search%'", conn)
cmd.Parameters.AddWithValue("#search", queryTerm)
Using dr = cmd.ExecuteReader()
While dr.Read()
' Update conversions according to actual data types
' here as well as in the class I provided.
results.Add(New Result(
Convert.ToInt32(dr("id")),
dr("room_no").ToString(),
dr("name").ToString(),
dr("description").ToString(),
Convert.ToDecimal(dr("price"))))
End While
End Using
End Using
End Using
' Can't update the UI from a background thread, so this call is invoked
DataGridView1.Invoke(
Sub()
DataGridView1.DataSource = Nothing
DataGridView1.DataSource = results
End Sub)
End Sub
Additional information is in remarks in the code provided

How to use a variable for the criteria in a query to restrict the query to the active form?

I have form named "frmBond-MuniDetailsAE". It has a combo box named "cboStep". The Row Source for cboSteps is an embedded query that retrieves records from a table named "tblBond-Steps", and it has as Criteria -
[Forms]![frmBond-MuniDetailsAE]![SYM]. This restricts the query to records in tblBond-Steps to only those that have a SYM field that matches that field in the form. This works fine. But I would like to be able to copy and reuse the form for other types of bonds, and I don't want to have to rewrite the embedded query in each copied form. So I wanted to use a variable in the query criteria that would reference the current form.
Following answers given in StackOverflow at How do I reference the current form in an expression in Microsoft Access?, I wrote a Public Function named "FormName()". Here is the function:
Public Function FormName() As String
Dim frmCurrentForm As Form
Set frmCurrentForm = Screen.ActiveForm
FormName = "[Form]![" & frmCurrentForm.Name & "]" & "![SYM]"
End Function
Then in the embedded query for the combo box, I entered "FormName()" as the criteria. Here is the SQL for that query:
SELECT [tblBond-Steps].SYM, [StepDate] & " # " & [Cpn] AS Steps, Format([tblBond-Steps].
[StepCpn],"0.0000%") AS Cpn, [tblBond-Steps].StepDate
FROM [tblBond-Steps]
WHERE ((([tblBond-Steps].SYM)=FormName()))
ORDER BY [tblBond-Steps].StepDate;
But when I open the form with the above query as the Row Source for cboSteps, I get VBA Run-time error '2475': "You entered an expression that requires a form to be the active window."
I can't figure out what I'm doing wrong. Can someone help me?
You must return the value, not the expression:
Public Function FormName() As String
Dim frmCurrentForm As Form
Set frmCurrentForm = Screen.ActiveForm
FormName = frmCurrentForm![SYM].Value
End Function

Outlook Macro's: Get user initials

I am working on a very, very simple project which sets a followup Flag on a selected message when running a macro.
I have created this so far which works very nicely, but I want to improve it by replacing the manual input of "YA" initials and put the default profile user initials as the initials.
I have found the contactitem object, but I have no idea how to get the initials out of it to put it as a .FlagRequest
Any idea's about this?
This is currently my code: (the GetCurrentItem just returns the selected email)
Public Sub SetCustomFlagNormal()
Dim objMsg As Object
Set objMsg = GetCurrentItem()
With objMsg
.MarkAsTask olMarkThisWeek
.TaskDueDate = Now
.FlagRequest = "YA"
.ReminderSet = True
.ReminderTime = Now + 2
.Save
End With
Set objMsg = Nothing
End Sub
The Outlook object model provides the CurrentUser property for the Namespace and Account classes. The property of the Namespace class returns the display name of the currently logged-on user as a Recipient object.
Sub DisplayCurrentUser()
Dim myNamespace As Outlook.NameSpace
Set myNameSpace = Application.GetNameSpace("MAPI")
MsgBox myNameSpace.CurrentUser
End Sub
The property of the Account class returns a Recipient object that represents the current user identity for the account. See the Name property of the Recipient class.
I have finally found a way.
After getting to multiple website, I was able to determine that Outlook doesn't offer a way to get the user initials and that Word has to be called upon to get the initials
As office uses the same initials throughout all office applications.
I got my response on this website.
http://blogs.technet.com/b/heyscriptingguy/archive/2008/03/18/how-can-i-retrieve-the-user-name-and-user-initials-from-microsoft-powerpoint.aspx
Hope it helps

"Query is not understandable" - Full text searching where field types have changed

A client have a long lived IBM Notes application where someone along the line changed the type of a field from number to text.
So, now when we're trying to do an FT search like: [myField] = "1234" receive the error message: "Query is not understandable".
If I do: [myField] = 1234 it works but won't return any hits. Even though there's a document where myField = "1234".
The field is of type text in the design.
I've created a new view for testing, only allowing documents from one form.
Deleted the full text index (even on the file system)
updall -X
Fixup -r
Created full text index
In my test view I've got one column that shows if the field content being searched is of type text #IsText(myField) and all rows shows: 1 (so it's field content must be text)
None of the above worked so I created a new database copy locally.
Same problem.
Created an entirely new database (for testing only), form, view and full text index and that works.
Feels like the existing database design somewhere stores the old field type...
Any ideas appreciated.
Thanks!
/J
Datatypes and field names are stored in the UNK table. There is just one entry per field name, so it's critical not to use the same field name more than once in an application with different datatypes.
You need to rebuild the UNK table, as I blogged here http://www.intec.co.uk/full-text-search-musings/
Note, it must be an offline compact, as Duffbert says here http://www.duffbert.com/duffbert/blog.nsf/d6plinks/TDUF-5SMHV4. If anyone is in the database when you do the compact, it will fail and the UNK table will not be rebuilt.
Links are useful, but if you don't want to remove data from documents - for me such steps worked (and there was no need in removing fields from forms in designer):
Run from designer with manager access with such code inside
Sub Initialize
Dim s As New NotesSession
Dim db As NotesDatabase
Dim dc As NotesDocumentCollection
Dim doc As NotesDocument
Dim i As Integer
Dim nc As NotesNoteCollection
Dim noteid As String
Dim nextnoteid As string
Dim itemArr As Variant
Dim NeedSave As Boolean
Const ITEM_NAME = "itemName1|itemName2"
itemArr = Split( ITEM_NAME, "|" )
'погромист-кун не должен забывать про наличие итемов в формах...
Set db = s.Currentdatabase
Set nc = db.CreateNoteCollection(False)
nc.SelectForms = true
Call nc.BuildCollection
noteid = nc.Getfirstnoteid()
For i = 1 To nc.Count
Set doc = db.Getdocumentbyid( noteid )
noteid = nc.Getnextnoteid( noteid )
NeedSave = false
ForAll IA In itemArr
If doc.Hasitem( IA ) Then
Call doc.Removeitem( IA )
NeedSave = true
End If
End ForAll
If NeedSave Then
Call doc.Save( True, False )
End If
Print CStr( i ) & "\" & CStr( nc.Count )
Next
End Sub
Remove database index
Run from administrator command lo compact database.nsf -c , like mentioned in links above
Create index

How to make a ComboBox column with two data sources (for DataGridView)

The data sources have the same structure, but different data. One would be used for rows that are saved (view mode), and the other one would be for rows that are being added or edited (edit/new rows). How can that be acomplished?
I have a standard foreign key column that references a standard lookup table which has an ID, Name and Active (bit). The combo box column uses that lookup table to show the list, but only active items. Let's say a lookup item is used and later deactivated (Active = 0). The combo box column now shows errors because the ID is not found in the list. Does anyone have any ideas how to solve it?
Not sure if you're still looking but I've just come across the same problem. Here's how I addressed it, hope it is of use to you.
Define a function which returns a DataGridViewComboCell with the appropriate datasource set (collection objects defined elsewhere, note that I'm using EntitySpaces in this example to populate the DataSource):
Private Function GetStockComboDataSource(ByVal type As eStockComboType) As DataGridViewComboBoxCell
Try
Dim cell As New DataGridViewComboBoxCell
Select Case type
Case eStockComboType.StockIn
cell.DataSource = Me.StockInCol.Query.LoadDataTable
cell.DisplayMember = "FullName"
cell.ValueMember = JCStockInMetadata.ColumnNames.StockItemID
Case eStockComboType.StockItem
cell.DataSource = StockItemCol.Query.LoadDataTable
cell.ValueMember = JCStockItemMetadata.ColumnNames.StockItemID
cell.DisplayMember = "FullName"
End Select
Return cell
End Function
Now when it comes to setting the combo DataSource (I use the RowEnter event here for example):
Private Sub dgvStock_RowEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvStock.RowEnter
Try
If IsNumeric(Me.dgvStock.Rows(e.RowIndex).Cells("ID").Value) Then
Dim intValue As Integer = Convert.ToInt32(Me.dgvStock.Rows(e.RowIndex).Cells("Stock Item").Value)
Me.dgvStock.Rows(e.RowIndex).Cells("Stock Item") = GetStockComboDataSource(eStockComboType.StockItem)
Me.dgvStock.Rows(e.RowIndex).Cells("Stock Item").Value = intValue
Else
Me.dgvStock.Rows(e.RowIndex).Cells("Stock Item") = GetStockComboDataSource(eStockComboType.StockIn)
End If
Catch ex As Exception
JCExceptionLogger.LogException(ex)
End Try
End Sub
Here I switch the combo DataSource depending on whether the ID column is numeric but you can implement whatever business logic you require. Note that I save the value of the cell before setting the combo (intValue). This appears to be necessary otherwise the combo will display as blank.

Resources