Create a menu with predefined text from excel file Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
WilburBr
Posts: 15
Joined: 22 Jun 2019, 22:17

Create a menu with predefined text from excel file

15 Jul 2019, 06:43

Hello =) :)

i would like to create a menu with some names, based on a excel file data, and, when clicking on the desired name, send the corresponding number.

I.e.

excel:
column A | column B
NameA | 3652
NameB | 6546
NameC | 3546

Menu created:
NameA
NameB
NameC

so, when i click NameA, send "3652"; if i click NameB, send "6546" and so on

is it possible? Or it would be easier to use an .ini file?

thanks :) :)
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: Create a menu with predefined text from excel file

15 Jul 2019, 15:02

Excel file is a bit difficult and slower to read. CSV file is a better choice, easy to read from AHK, and still able to edit in Excel.

Here is an example:

Code: Select all

Menu1 := new CsvMenu("D:\Desktop\menu.csv", "Menu1_OnClick")
return

F1::Menu1.Show()

Menu1_OnClick(Command, ItemName, ItemPos, MenuName) {
	SendInput, {Text}%Command%
}

class CsvMenu
{
	__New(FileName, FunctionName) {
		Loop, Read, %FileName%
		{
			col := StrSplit(A_LoopReadLine, ",")
			fn := Func(FunctionName).Bind(col.2)
			Menu, % &this, Add, % col.1, % fn
		}
	}

	__Delete() {
		Menu, % &this, Delete
	}

	Show() {
		Menu, % &this, Show
	}
}
Another example:

Code: Select all

MenuName := CreateMenuFromCsv("D:\Desktop\menu.csv")
return

F1::Menu, %MenuName%, Show

CreateMenuFromCsv(FileName) {
	if InStr(FileName, "*")
	{
		SendInput, % "{Text}" SubStr(FileName, 2)
		return
	}

	MenuName := Func(A_ThisFunc).Bind(["I just want a random name.."])

	Loop, Read, %FileName%
	{
		col := StrSplit(A_LoopReadLine, ",")
		fn := Func(A_ThisFunc).Bind("*" col.2)
		Menu, % &MenuName, Add, % col.1, % fn
	}
	return &MenuName
}
WilburBr
Posts: 15
Joined: 22 Jun 2019, 22:17

Re: Create a menu with predefined text from excel file

15 Jul 2019, 15:41

Hello.
Many thanks for the reply. :)
as soon as I return home I will read more calmly and try to understand the examples you shared :lol: :lol: :lol: :D .
WilburBr
Posts: 15
Joined: 22 Jun 2019, 22:17

Re: Create a menu with predefined text from excel file

16 Jul 2019, 11:57

tmplinshi wrote:
15 Jul 2019, 15:02
Excel file is a bit difficult and slower to read. CSV file is a better choice, easy to read from AHK, and still able to edit in Excel.

Here is an example:

Code: Select all

Menu1 := new CsvMenu("D:\Desktop\menu.csv", "Menu1_OnClick")
return

F1::Menu1.Show()

Menu1_OnClick(Command, ItemName, ItemPos, MenuName) {
	SendInput, {Text}%Command%
}

class CsvMenu
{
	__New(FileName, FunctionName) {
		Loop, Read, %FileName%
		{
			col := StrSplit(A_LoopReadLine, ",")
			fn := Func(FunctionName).Bind(col.2)
			Menu, % &this, Add, % col.1, % fn
		}
	}

	__Delete() {
		Menu, % &this, Delete
	}
	

	Show() {
		Menu, % &this, Show
	}
}
Another example:

Code: Select all

MenuName := CreateMenuFromCsv("D:\Desktop\menu.csv")
return

F1::Menu, %MenuName%, Show

CreateMenuFromCsv(FileName) {
	if InStr(FileName, "*")
	{
		SendInput, % "{Text}" SubStr(FileName, 2)
		return
	}

	MenuName := Func(A_ThisFunc).Bind(["I just want a random name.."])

	Loop, Read, %FileName%
	{
		col := StrSplit(A_LoopReadLine, ",")
		fn := Func(A_ThisFunc).Bind("*" col.2)
		Menu, % &MenuName, Add, % col.1, % fn
	}
	return &MenuName
}
:bravo: :bravo: :bravo: :dance: :dance: :dance:
Amazing! Thank you :bravo: :bravo:
WilburBr
Posts: 15
Joined: 22 Jun 2019, 22:17

Re: Create a menu with predefined text from excel file

16 Jul 2019, 13:03

It's working perfectly: D

I was able to make some names that I wanted disabled by placing after the loop - "Menu,% & MenuName, Disable, NAME TO DISABLE"

But I tried modifying it to create submenus, without success = (


is it possible, by editing the csv file, determining the names to be disabled and which should be submenus? or these changes must be included in the ahk script?
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: Create a menu with predefined text from excel file  Topic is solved

18 Jul 2019, 00:51

Ok, here it is:

Code: Select all

menuData =
(
.Disabled Item
Item1 = 111
---
Item2 = 222
Item3
	.This is a sub menu
	---
	Item3-1 = 31
	Item3-2
		Item3-2-1 = 321
		Item3-2-2 = 322
	Item3-3 = 33
Item4 = 444
)

menu1 := new textMenu(menuData, "OnMenuSelect")
; menu2 := new textMenu("D:\Desktop\menu2.txt", "OnMenuSelect")
return

F1::menu1.show()

OnMenuSelect(Command, ItemName, ItemPos, MenuName) {
	SendInput, {Text}%Command%
}

class textMenu
{
	__New(ByRef VariableOrFileName, FunctionName := "") {
		if !IsFunc(FunctionName)
			throw FunctionName " is not a valid function name"

		this.dat := this.dataToArray(VariableOrFileName)
		this.fn := FunctionName
		this.menuName := &this

		for i, line in this.dat
		{
			if tabCount := this.isSubMenu(i)
				this.begin_subMenu(i, tabCount)
			else
			{
				line := LTrim(line, "`t")

				this.addMenu(line)

				if (SubStr(line, 1, 1) = ".")
					Menu, % this.menuName, Disable, % SubStr(line, 2)

				if this.isEndOfSubMenu(i)
					this.add_subMenu()
			}
		}

		this.dat := this.fn := this.subMenu := ""
	}

	__Delete() {
		Menu, % this.menuName, Delete
	}

	addMenu(ByRef line) {
		if (line ~= "^-{3,}")
			Menu, % this.menuName, Add
		else
		{
			if !RegExMatch(line, "^(.*?)\s*=\s*(.*)$", m) {
				m1 := line
			}
			m1 := LTrim(m1, ".")
			fn := Func(this.fn).Bind(m2)
			Menu, % this.menuName, Add, % m1, % fn
		}
	}

	nextLineTabCount(i) {
		if ( i+1 <= this.dat.MaxIndex() )
		&& ( RegExMatch(this.dat[i+1], "P)^\t+", tabCount) )
			return tabCount
	}

	isEndOfSubMenu(i) {
		return this.nextLineTabCount(i) < this.subMenu.tabCount
	}

	isSubMenu(i) {
		tabs := this.nextLineTabCount(i)
		return (tabs > this.subMenu.tabCount) ? tabs : 0
	}

	begin_subMenu(i, tabCount) {
		this.subMenu := { name: this.menuName
		                 , text: LTrim(this.dat[i], "`t")
		                 , tabCount: tabCount
		                 , pre_subMenu: this.subMenu }
		this.menuName := &this "_" i
	}

	add_subMenu() {
		Menu, % this.subMenu.name, Add, % this.subMenu.text, % ":" this.menuName
		this.menuName := this.subMenu.name
		this.subMenu := this.subMenu.pre_subMenu
	}

	dataToArray(ByRef VariableOrFileName) {
		if FileExist(VariableOrFileName)
			content := FileOpen(VariableOrFileName, "r").Read()
		else
			content := VariableOrFileName
		
		content := Trim(content, "`r`n")
		content := RegExReplace(content, "\R+", "`n")
		return StrSplit(content, "`n", "`r")
	}

	show() {
		Menu, % this.menuName, Show
	}
}
Usage:

Code: Select all

menu1 := new textMenu(VariableOrFileName, FunctionName)
menu1.show()
Rules:
  • Line started with dot . will be disabled
  • Line started with Tab character will become a sub menu
  • Line started with --- will become a separator
WilburBr
Posts: 15
Joined: 22 Jun 2019, 22:17

Re: Create a menu with predefined text from excel file

22 Jul 2019, 10:53

Im speechless to thank you for your willingness to help :D


I'll look line by line of code to try to understand and learn

thank you very much. :bravo:

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: gkaoyan, Joey5 and 197 guests