func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) {
	xlsx := f.workSheetReader(sheet)
	axis = f.mergeCellsParser(xlsx, axis)
	linkTypes := map[string]xlsxHyperlink{
		"External": {},
		"Location": {Location: link},
	}
	hyperlink, ok := linkTypes[linkType]
	if !ok || axis == "" {
		return
	}
	hyperlink.Ref = axis
	if linkType == "External" {
		rID := f.addSheetRelationships(sheet, SourceRelationshipHyperLink, link, linkType)
		hyperlink.RID = "rId" + strconv.Itoa(rID)
	}
	if xlsx.Hyperlinks == nil {
		xlsx.Hyperlinks = &xlsxHyperlinks{}
	}
	xlsx.Hyperlinks.Hyperlink = append(xlsx.Hyperlinks.Hyperlink, hyperlink)
}
SetCellHyperLink provides function to set cell hyperlink by given worksheet
name and link URL address. LinkType defines two types of hyperlink "External"
for web site or "Location" for moving to one of cell in this workbook. The
below is example for external link.

xlsx.SetCellHyperLink("Sheet1", "A3", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
// Set underline and font color style for the cell.
style, _ := xlsx.NewStyle(`{"font":{"color":"#1265BE","underline":"single"}}`)
xlsx.SetCellStyle("Sheet1", "A3", "A3", style)

A this is another example for "Location":

xlsx.SetCellHyperLink("Sheet1", "A3", "Sheet1!A40", "Location")
package excelize
import (
	"encoding/xml"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"
)
func (f *File) mergeCellsParser(xlsx *xlsxWorksheet, axis string) string {
	axis = strings.ToUpper(axis)
	if xlsx.MergeCells != nil {
		for i := 0; i < len(xlsx.MergeCells.Cells); i++ {
			if checkCellInArea(axis, xlsx.MergeCells.Cells[i].Ref) {
				axis = strings.Split(xlsx.MergeCells.Cells[i].Ref, ":")[0]
			}
		}
	}
	return axis
}
func (f *File) SetCellValue(sheet, axis string, value interface{}) {
	switch t := value.(type) {
	case float32:
		f.SetCellDefault(sheet, axis, strconv.FormatFloat(float64(value.(float32)), 'f', -1, 32))
	case float64:
		f.SetCellDefault(sheet, axis, strconv.FormatFloat(float64(value.(float64)), 'f', -1, 64))
	case string:
		f.SetCellStr(sheet, axis, t)
	case []byte:
		f.SetCellStr(sheet, axis, string(t))
	case time.Duration:
		f.SetCellDefault(sheet, axis, strconv.FormatFloat(float64(value.(time.Duration).Seconds()/86400), 'f', -1, 32))
		f.setDefaultTimeStyle(sheet, axis, 21)
	case time.Time:
		f.SetCellDefault(sheet, axis, strconv.FormatFloat(float64(timeToExcelTime(timeToUTCTime(value.(time.Time)))), 'f', -1, 64))
		f.setDefaultTimeStyle(sheet, axis, 22)
	case nil:
		f.SetCellStr(sheet, axis, "")
	case bool:
		f.SetCellBool(sheet, axis, bool(value.(bool)))
	default:
		f.setCellIntValue(sheet, axis, value)
	}
}
func (f *File) setCellIntValue(sheet, axis string, value interface{}) {
	switch value.(type) {
	case int:
		f.SetCellInt(sheet, axis, value.(int))
	case int8:
		f.SetCellInt(sheet, axis, int(value.(int8)))
	case int16:
		f.SetCellInt(sheet, axis, int(value.(int16)))
	case int32:
		f.SetCellInt(sheet, axis, int(value.(int32)))
	case int64:
		f.SetCellInt(sheet, axis, int(value.(int64)))
	case uint:
		f.SetCellInt(sheet, axis, int(value.(uint)))
	case uint8:
		f.SetCellInt(sheet, axis, int(value.(uint8)))
	case uint16:
		f.SetCellInt(sheet, axis, int(value.(uint16)))
	case uint32:
		f.SetCellInt(sheet, axis, int(value.(uint32)))
	case uint64:
		f.SetCellInt(sheet, axis, int(value.(uint64)))
	default:
		f.SetCellStr(sheet, axis, fmt.Sprintf("%v", value))
	}
}
func (f *File) SetCellBool(sheet, axis string, value bool) {
	xlsx := f.workSheetReader(sheet)
	axis = f.mergeCellsParser(xlsx, axis)
	col := string(strings.Map(letterOnlyMapF, axis))
	row, err := strconv.Atoi(strings.Map(intOnlyMapF, axis))
	if err != nil {
		return
	}
	xAxis := row - 1
	yAxis := TitleToNumber(col)
	rows := xAxis + 1
	cell := yAxis + 1
	completeRow(xlsx, rows, cell)
	completeCol(xlsx, rows, cell)
	xlsx.SheetData.Row[xAxis].C[yAxis].S = f.prepareCellStyle(xlsx, cell, xlsx.SheetData.Row[xAxis].C[yAxis].S)
	xlsx.SheetData.Row[xAxis].C[yAxis].T = "b"
	if value {
		xlsx.SheetData.Row[xAxis].C[yAxis].V = "1"
	} else {
		xlsx.SheetData.Row[xAxis].C[yAxis].V = "0"
	}
}
func (f *File) GetCellValue(sheet, axis string) string {
	xlsx := f.workSheetReader(sheet)
	axis = f.mergeCellsParser(xlsx, axis)
	row, err := strconv.Atoi(strings.Map(intOnlyMapF, axis))
	if err != nil {
		return ""
	}
	xAxis := row - 1
	rows := len(xlsx.SheetData.Row)
	if rows > 1 {
		lastRow := xlsx.SheetData.Row[rows-1].R
		if lastRow >= rows {
			rows = lastRow
		}
	}
	if rows < xAxis {
		return ""
	}
	for k := range xlsx.SheetData.Row {
		if xlsx.SheetData.Row[k].R == row {
			for i := range xlsx.SheetData.Row[k].C {
				if axis == xlsx.SheetData.Row[k].C[i].R {
					val, _ := xlsx.SheetData.Row[k].C[i].getValueFrom(f, f.sharedStringsReader())
					return val
				}
			}
		}
	}
	return ""
}
func (f *File) formattedValue(s int, v string) string {
	if s == 0 {
		return v
	}
	styleSheet := f.stylesReader()
	ok := builtInNumFmtFunc[styleSheet.CellXfs.Xf[s].NumFmtID]
	if ok != nil {
		return ok(styleSheet.CellXfs.Xf[s].NumFmtID, v)
	}
	return v
}
func (f *File) GetCellStyle(sheet, axis string) int {
	xlsx := f.workSheetReader(sheet)
	axis = f.mergeCellsParser(xlsx, axis)
	col := string(strings.Map(letterOnlyMapF, axis))
	row, err := strconv.Atoi(strings.Map(intOnlyMapF, axis))
	if err != nil {
		return 0
	}
	xAxis := row - 1
	yAxis := TitleToNumber(col)
	rows := xAxis + 1
	cell := yAxis + 1
	completeRow(xlsx, rows, cell)
	completeCol(xlsx, rows, cell)
	return f.prepareCellStyle(xlsx, cell, xlsx.SheetData.Row[xAxis].C[yAxis].S)
}
func (f *File) GetCellFormula(sheet, axis string) string {
	xlsx := f.workSheetReader(sheet)
	axis = f.mergeCellsParser(xlsx, axis)
	row, err := strconv.Atoi(strings.Map(intOnlyMapF, axis))
	if err != nil {
		return ""
	}
	xAxis := row - 1
	rows := len(xlsx.SheetData.Row)
	if rows > 1 {
		lastRow := xlsx.SheetData.Row[rows-1].R
		if lastRow >= rows {
			rows = lastRow
		}
	}
	if rows < xAxis {
		return ""
	}
	for k := range xlsx.SheetData.Row {
		if xlsx.SheetData.Row[k].R == row {
			for i := range xlsx.SheetData.Row[k].C {
				if axis == xlsx.SheetData.Row[k].C[i].R {
					if xlsx.SheetData.Row[k].C[i].F != nil {
						return xlsx.SheetData.Row[k].C[i].F.Content
					}
				}
			}
		}
	}
	return ""
}
func (f *File) SetCellFormula(sheet, axis, formula string) {
	xlsx := f.workSheetReader(sheet)
	axis = f.mergeCellsParser(xlsx, axis)
	col := string(strings.Map(letterOnlyMapF, axis))
	row, err := strconv.Atoi(strings.Map(intOnlyMapF, axis))
	if err != nil {
		return
	}
	xAxis := row - 1
	yAxis := TitleToNumber(col)
	rows := xAxis + 1
	cell := yAxis + 1
	completeRow(xlsx, rows, cell)
	completeCol(xlsx, rows, cell)
	if xlsx.SheetData.Row[xAxis].C[yAxis].F != nil {
		xlsx.SheetData.Row[xAxis].C[yAxis].F.Content = formula
	} else {
		f := xlsxF{
			Content: formula,
		}
		xlsx.SheetData.Row[xAxis].C[yAxis].F = &f
	}
}