I'm getting values from range that I specified. But is there a way to count those values?
I'm using this method to get values from the sheets.
spreadsheetId :=""
range2 :=""
valueRenderOption := "FORMATTED_VALUE"
resp, err :=sheetsService.Spreadsheets.Values.Get(spreadsheetId, range2).ValueRenderOption(valueRenderOption).Do()
if err != nil {
log.Fatal(err)
}
Modification points:
For sheetsService.Spreadsheets.Values.Get(spreadsheetId, range2).ValueRenderOption(valueRenderOption).Do(), when A1:C1 gives to range2, the returned value is {"majorDimension":"ROWS","range":"A1:C1","values":[["###","###","###"]]}. In this case, resp.Values is 2 dimensional array. By this, len(resp.Values) returns 1. I think that this is the reason of your issue.
When you want to retrieve the total number of cells from sheetsService.Spreadsheets.Values.Get(spreadsheetId, range2).ValueRenderOption(valueRenderOption).Do(), how about the following modification?
Modified script:
resp, err := sheetsService.Spreadsheets.Values.Get(spreadsheetId, range2).ValueRenderOption(valueRenderOption).Do()
if err != nil {
log.Fatal(err)
}
count := 0
for _, e := range resp.Values {
count += len(e)
}
fmt.Println(count)
In this case, when A1:C1 is used for range2, 3 is returned.
Note:
For example, when you want to retrieve the total number of cells which are not empty, you can also use the following script.
resp, err := sheetsService.Spreadsheets.Values.Get(spreadsheetId, range2).ValueRenderOption(valueRenderOption).Do()
if err != nil {
log.Fatal(err)
}
count := 0
for _, e := range resp.Values {
for _, f := range e {
if f != "" {
count++
}
}
}
fmt.Println(count)
In this modified script, it supposes that you have already been able to retrieve the values from Google Spreadsheet using Sheets API. Please be careful this.
Reference:
Method: spreadsheets.values.get
Related
I am unable to get the full data emitted from SC event by using types.Log channel. Is there any way so that I can have all the data from an event emitted?
The event I'm trying to parse:
PairCreated(address indexed,address indexed,address,uint)
My code:
for {
select {
case err := <-sub.Err():
log.Fatal(err)
case vLog := <-logs:
fmt.Printf("Log Block Number: %d\n", vLog.BlockNumber)
fmt.Printf("Log Index: %d\n", vLog.Index)
event := make(map[string]interface{})
err := contractAbi.UnpackIntoMap(event, "PairCreated", vLog.Data)
if err != nil {
log.Fatal(err)
}
fmt.Println(event)
}
}
I could only parse the last two arguments of the event.
I understood what was wrong here.
If an argument is declared as indexed that argument goes to Topics instead of Data. And there can be at most 3 topics. So, I tried to unpack the topics but failed. And succeeded with the following way:
token1 := common.HexToAddress(vLog.Topics[1].Hex())
token2 := common.HexToAddress(vLog.Topics[2].Hex())
And pair was in Data
So, the final code is:
for {
select {
case err := <-sub.Err():
log.Fatal(err)
case vLog := <-logs:
fmt.Printf("Log Block Number: %d\n", vLog.BlockNumber)
fmt.Printf("Log Index: %d\n", vLog.Index)
event := make(map[string]interface{})
err := contractAbi.UnpackIntoMap(event, "PairCreated", vLog.Data)
if err != nil {
log.Fatal(err)
}
fmt.Println(event)
token1 := common.HexToAddress(vLog.Topics[1].Hex())
token2 := common.HexToAddress(vLog.Topics[2].Hex())
}
}
I'm trying to read a list of registry names under the given key, but i get an empty slice of strings, instead of actual registry data. Anything i'm doing incorrectly here?
Expected result: []string{"ApplicationBase", "RunTimeVersion", ...}
Actual result printed by CMD: "PS Sub Key Names: []"
k, err := registry.OpenKey(registry.LOCAL_MACHINE,`SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine`, registry.QUERY_VALUE|registry.ENUMERATE_SUB_KEYS)
if err != nil {
log.Fatal(err)
}
defer k.Close()
sn, err := k.ReadSubKeyNames(-1)
if err != nil {
log.Fatal(err)
}
fmt.Printf("PS Sub Key Names: %q\n", sn)
I figured it out - should have used (k Key)ReadValueNames to get keys of values.
I have the ff:
func getSlice(distinctSymbols []string) []symbols {
// Prepare connection
stmt1, err := db.Prepare("Select count(*) from stockticker_daily where symbol = $1;")
checkError(err)
defer stmt1.Close()
stmt2, err := db.Prepare("Select date from stockticker_daily where symbol = $1 order by date asc limit 1;")
checkError(err)
defer stmt2.Close()
var symbolsSlice []symbols
c := make(chan symbols)
for _, symbol := range distinctSymbols {
go worker(symbol, stmt1, stmt2, c)
**symbolsFromChannel := <-c**
**symbolsSlice = append(symbolsSlice, symbolsFromChannel})**
}
return symbolsSlice
}
func worker(symbol string, stmt1 *sql.Stmt, stmt2 *sql.Stmt, symbolsChan chan symbols) {
var countdp int
var earliestdate string
row := stmt1.QueryRow(symbol)
if err := row.Scan(&countdp); err != nil {
log.Fatal(err)
}
row = stmt2.QueryRow(symbol)
if err := row.Scan(&earliestdate); err != nil {
log.Fatal(err)
}
symbolsChan <- symbols{symbol, countdp, earliestdate}
}
Please take a look at the first function, I know it won't work as I expect since the line symbolsFromChannel := <-c will block until it receives from the channel, so the iteration on the goroutine go worker will not continue unless the block is removed. What is the best or correct way to do that?
Just do the loop twice, e.g.
for _, symbol := range distinctSymbols {
go worker(symbol, stmt1, stmt2, c)
}
for range distinctSymbols {
symbolsSlice = append(symbolsSlice, <-c)
}
I'm trying to add multiple plots by using a loop, but I can't seem to figure out how to put the lines in. Here is the code I'm working on:
func plot_stochastic_processes(processes [][]float64, title string) {
p, err := plot.New()
if err != nil {
panic(err)
}
p.Title.Text = title
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
err = plotutil.AddLinePoints(p,
"Test", getPoints(processes[1]),
//Need to figure out how to loop through processes
)
if err != nil {
panic(err)
}
// Save the plot to a PNG file.
if err := p.Save(4*vg.Inch, 4*vg.Inch, "points.png"); err != nil {
panic(err)
}
}
My getPoints function looks like this:
func getPoints(line []float64) plotter.XYs {
pts := make(plotter.XYs, len(line))
for j, k := range line {
pts[j].X = float64(j)
pts[j].Y = k
}
return pts
}
I get an error when trying to put a loop where the commented section is. I know this should be fairly straightforward. Perhaps a loop prior to this to get the list of lines?
Something like
for i, process := range processes {
return "title", getPoints(process),
}
Obviously I know that isn't correct, but not I'm not sure how to go about it.
I think you want to first extract your data into a []interface{}, and then call into AddLinePoints. Roughly (I didn't test):
lines := make([]interface{},0)
for i, v := range processes {
lines = append(lines, "Title" + strconv.Itoa(i))
lines = append(lines, getPoints(v))
}
plotutil.AddLinePoints(p, lines...)
i am trying to write to to a file. i read the whole content of the file and now i want to change the content of the file based on some word that i have got from the file. but when i check, the content of the file, it is still the same and it has not change. this is what i used
if strings.Contains(string(read), sam) {
fmt.Println("this file contain that word")
temp := strings.ToUpper(sam)
fmt.Println(temp)
err := ioutil.WriteFile(fi.Name(), []byte(temp), 0644)
} else {
fmt.Println(" the word is not in the file")
}
Considering that your call to ioutil.WriteFile() is consistent with what is used in "Go by Example: Writing Files", this should work.
But that Go by example article check the err just after the write call.
You check the err outside the scope of your test:
if matched {
read, err := ioutil.ReadFile(path)
//fmt.Println(string(read))
fmt.Println(" This is the name of the file", fi.Name())
if strings.Contains(string(read), sam) {
fmt.Println("this file contain that word")
Value := strings.ToUpper(sam)
fmt.Println(Value)
err = ioutil.WriteFile(fi.Name(), []byte(Value), 0644)
} else {
fmt.Println(" the word is not in the file")
}
check(err) <===== too late
}
The err you are testing is the one you got when reading the file (ioutil.ReadFile), because of blocks and scope.
You need to check the error right after the Write call
err = ioutil.WriteFile(fi.Name(), []byte(Value), 0644)
check(err) <===== too late
Since WriteFile overwrite the all file, you could strings.Replace() to replace your word by its upper case equivalent:
r := string(read)
r = strings.Replace(r, sam, strings.ToUpper(sam), -1)
err := ioutil.WriteFile(fi.Name(), []byte(r), 0644)
For a replace which is case insensitive, use a regexp as in "How do I do a case insensitive regular expression in Go?".
The, use func (*Regexp) ReplaceAllString:
re := regexp.MustCompile("(?i)\\b"+sam+"\\b")
r = re.ReplaceAllString(r, strings.ToUpper(sam))
err := ioutil.WriteFile(fi.Name(), []byte(r), 0644)
Note the \b: word boundary to find the any word starting and ending with sam content (instead of finding substrings containing sam content).
If you want to replace substrings, simply drop the \b:
re := regexp.MustCompile("(?i)"+sam)
It's not clear what you want to do. My best guess is something like this:
package main
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
)
func UpdateWord(filename string, data, word []byte) (int, error) {
n := 0
f, err := os.OpenFile(filename, os.O_WRONLY, 0644)
if err != nil {
return n, err
}
uWord := bytes.ToUpper(word)
if len(word) < len(uWord) {
err := errors.New("Upper case longer than lower case:" + string(word))
return n, err
}
if len(word) > len(uWord) {
uWord = append(uWord, bytes.Repeat([]byte{' '}, len(word))...)[:len(word)]
}
off := int64(0)
for {
i := bytes.Index(data[off:], word)
if i < 0 {
break
}
off += int64(i)
_, err = f.WriteAt(uWord, off)
if err != nil {
return n, err
}
n++
off += int64(len(word))
}
f.Close()
if err != nil {
return n, err
}
return n, nil
}
func main() {
// Test file
filename := `ltoucase.txt`
// Create test file
lcase := []byte(`update a bc def ghij update klmno pqrstu update vwxyz update`)
perm := os.FileMode(0644)
err := ioutil.WriteFile(filename, lcase, perm)
if err != nil {
fmt.Println(err)
return
}
// Read test file
data, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(data))
// Update word in test file
word := []byte("update")
n, err := UpdateWord(filename, data, word)
if err != nil {
fmt.Println(n, err)
return
}
fmt.Println(filename, string(word), n)
data, err = ioutil.ReadFile(filename)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(data))
}
Output:
update a bc def ghij update klmno pqrstu update vwxyz update
ltoucase.txt update 4
UPDATE a bc def ghij UPDATE klmno pqrstu UPDATE vwxyz UPDATE