C#調用js庫的方法

来源:https://www.cnblogs.com/s0611163/archive/2023/01/17/17056909.html
-Advertisement-
Play Games

前言 用.net6開發一個Winform程式,處理Excel文件,並把結果導出Excel文件。 要用到兩個演算法,一是turf.js庫的booleanPointInPolygon方法,判斷經緯度坐標是否在區域內;二是經緯度糾偏演算法,因為對方給的區域坐標集合有偏移,需要糾偏。 這兩個演算法,網上找C#的實 ...


前言

用.net6開發一個Winform程式,處理Excel文件,並把結果導出Excel文件。
要用到兩個演算法,一是turf.js庫的booleanPointInPolygon方法,判斷經緯度坐標是否在區域內;二是經緯度糾偏演算法,因為對方給的區域坐標集合有偏移,需要糾偏。
這兩個演算法,網上找C#的實現,一是不好找;二是找來的不信任,我還要測試以確保沒有問題。我之前做電子地圖使用過turf.js庫和js版本的糾偏演算法,比較信任,確定沒有問題。
所以我就打算通過C#調用js庫的方法,來實現數據處理。

安裝ClearScript

ClearScript是微軟開源的js引擎,支持windows、linux、mac。
NuGet搜索安裝:
Microsoft.ClearScript.Core
Microsoft.ClearScript.V8
Microsoft.ClearScript.V8.Native.win-x64

引入js文件


把leaflet.mapCorrection.js、turf.v6.5.0.min.js和自己寫的calc.js放入工程中,右擊屬性設置複製到輸出目錄:如果較新則複製。
calc.js通過調用leaflet.mapCorrection.js和turf.v6.5.0.min.js中的方法實現功能,文件內容如下:

function calc(lng, lat, polygonStr) {
    var point = turf.point([lng, lat]);
    var polygonPoints = JSON.parse(polygonStr);
    var polygon = turf.polygon(polygonPoints);

    var bl = turf.booleanPointInPolygon(point, polygon);
    return bl;
}

function correct(lng, lat) {
    var newPoint = new CoordConvertor().gcj02_To_gps84(lng, lat);
    return newPoint;
}

創建V8ScriptEngine對象

private V8ScriptEngine _engine = new V8ScriptEngine();

通過js引擎載入js文件

在Form1_Load方法中添加如下代碼:

_engine.AddHostType("Console", typeof(Console));
string fileName = AppDomain.CurrentDomain.BaseDirectory + "turf.v6.5.0.min.js";
string js;
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    byte[] bArr = new byte[fs.Length];
    await fs.ReadAsync(bArr, 0, bArr.Length);
    js = ASCIIEncoding.UTF8.GetString(bArr);
}
_engine.Execute(js);
fileName = AppDomain.CurrentDomain.BaseDirectory + "calc.js";
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    byte[] bArr = new byte[fs.Length];
    await fs.ReadAsync(bArr, 0, bArr.Length);
    js = ASCIIEncoding.UTF8.GetString(bArr);
}
_engine.Execute(js);
fileName = AppDomain.CurrentDomain.BaseDirectory + "leaflet.mapCorrection.js";
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    byte[] bArr = new byte[fs.Length];
    await fs.ReadAsync(bArr, 0, bArr.Length);
    js = ASCIIEncoding.UTF8.GetString(bArr);
}
_engine.Execute(js);

C#調用js方法實現經緯度坐標糾偏

double lng = Convert.ToDouble(lnglat[0]);
double lat = Convert.ToDouble(lnglat[1]);

//坐標糾偏
dynamic newPoint = _engine.Invoke("correct", new object[] { lng, lat });
lng = newPoint.lng;
lat = newPoint.lat;

C#調用js方法判斷經緯度點位是否在多邊形內

//_selectedRegionPoints是多邊形坐標點位集合json字元串
bool bl = (bool)_engine.Invoke("calc", new object[] { lng, lat, _selectedRegionPoints });

程式開發完成後發佈


發佈後文件夾拷貝到用戶的win10系統中可以直接使用,不需要安裝.net6環境。我自己的很老的win7 sp1虛擬機上跑不起來,ClearScriptV8.win-x64.dll無法載入成功,暫不知道為什麼。

Form1.cs完整代碼如下:

當時程式寫的急,當然,程式還可以優化,不過沒必要,要處理的數據量不大,功能沒問題就行。

using Models;
using Newtonsoft.Json;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.ClearScript.JavaScript;
using Microsoft.ClearScript.V8;
using NPOI.HSSF.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.SS.UserModel;
using System.Reflection;
using System.Windows.Forms;
using NPOI.Util;

namespace 點位
{
    public partial class Form1 : Form
    {
        private Regions _regions;
        private List<CameraInfo> _cameraList = new List<CameraInfo>();
        private V8ScriptEngine _engine = new V8ScriptEngine();
        private string _selectedRegionPoints;

        public Form1()
        {
            InitializeComponent();
        }

        private async void Form1_Load(object sender, EventArgs e)
        {
            //通過js引擎載入js文件
            _engine.AddHostType("Console", typeof(Console));
            string fileName = AppDomain.CurrentDomain.BaseDirectory + "turf.v6.5.0.min.js";
            string js;
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] bArr = new byte[fs.Length];
                await fs.ReadAsync(bArr, 0, bArr.Length);
                js = ASCIIEncoding.UTF8.GetString(bArr);
            }
            _engine.Execute(js);
            fileName = AppDomain.CurrentDomain.BaseDirectory + "calc.js";
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] bArr = new byte[fs.Length];
                await fs.ReadAsync(bArr, 0, bArr.Length);
                js = ASCIIEncoding.UTF8.GetString(bArr);
            }
            _engine.Execute(js);
            fileName = AppDomain.CurrentDomain.BaseDirectory + "leaflet.mapCorrection.js";
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] bArr = new byte[fs.Length];
                await fs.ReadAsync(bArr, 0, bArr.Length);
                js = ASCIIEncoding.UTF8.GetString(bArr);
            }
            _engine.Execute(js);

            //行政區划下拉列表初始化
            fileName = AppDomain.CurrentDomain.BaseDirectory + "安徽.json";
            using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] bArr = new byte[fs.Length];
                await fs.ReadAsync(bArr, 0, bArr.Length);
                string json = ASCIIEncoding.UTF8.GetString(bArr);
                _regions = JsonConvert.DeserializeObject<Regions>(json);
            }

            List<Records> citys = _regions.RECORDS.ToList().FindAll(a => a.civilcode.Length == 4);
            cbxCity.DataSource = citys;
            cbxCity.DisplayMember = "civilname";
            cbxCity.ValueMember = "civilcode";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            openFileDialog1.Title = "選擇要處理的Excel文件";
            openFileDialog1.Filter = "Excel文件(*.xlsx)|*.xlsx";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                using (FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {

                }
            }
        }


        private void cbxCity_SelectedIndexChanged(object sender, EventArgs e)
        {
            Records record = cbxCity.SelectedItem as Records;
            List<Records> citys = _regions.RECORDS.ToList().FindAll(a => a.civilcode.Length > 4 && a.civilcode.Substring(0, 4) == record.civilcode);
            citys.Insert(0, new Records() { civilcode = null, civilname = "==請選擇==" });
            cbxCounty.DataSource = citys;
            cbxCounty.DisplayMember = "civilname";
            cbxCounty.ValueMember = "civilcode";
        }

        private void cbxCounty_SelectedIndexChanged(object sender, EventArgs e)
        {
            Records record = cbxCounty.SelectedItem as Records;
            if (record.civilcode == null)
            {
                record = cbxCity.SelectedItem as Records;
            }
            Regex regex = new Regex(@"^POLYGON\((\(.*\),?)*\)$");
            var mc = regex.Matches(record.polygongeo);
            StringBuilder sb = new StringBuilder();
            foreach (Match m in mc)
            {
                string value = m.Groups[1].Value.TrimStart('(').TrimEnd(')');
                string[] lnglatArr = value.Split(',');
                bool first = true;
                if (sb.Length > 0)
                {
                    sb.Append(",");
                }
                sb.Append("[[");
                foreach (string lnglatStr in lnglatArr)
                {
                    string[] lnglat = lnglatStr.Trim().Split(' ');
                    double lng = Convert.ToDouble(lnglat[0]);
                    double lat = Convert.ToDouble(lnglat[1]);

                    //坐標糾偏
                    dynamic newPoint = _engine.Invoke("correct", new object[] { lng, lat });
                    lng = newPoint.lng;
                    lat = newPoint.lat;

                    if (first)
                    {
                        first = false;
                        sb.AppendFormat($"[{lng}, {lat}]");
                    }
                    else
                    {
                        sb.AppendFormat($",[{lng}, {lat}]");
                    }
                }
                sb.Append("]]");
            }
            _selectedRegionPoints = sb.ToString();
        }

        private async void openFileDialog1_FileOk(object sender, System.ComponentModel.CancelEventArgs e)
        {
            await Task.Delay(10);

            //讀取Excel
            _cameraList = new List<CameraInfo>();
            using (FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                XSSFWorkbook workbook = new XSSFWorkbook(fs);
                ISheet sheet = workbook.GetSheetAt(0);
                for (int i = 1; i <= sheet.LastRowNum; i++)
                {
                    IRow row = sheet.GetRow(i);
                    CameraInfo cameraInfo = new CameraInfo();
                    cameraInfo.CameraNo = row.GetCell(1).StringCellValue.Trim();
                    cameraInfo.City = row.GetCell(2).StringCellValue.Trim();
                    cameraInfo.County = row.GetCell(3).StringCellValue.Trim();
                    cameraInfo.CameraName = row.GetCell(4).StringCellValue.Trim();
                    cameraInfo.Lng = row.GetCell(5).StringCellValue.Trim();
                    cameraInfo.Lat = row.GetCell(6).StringCellValue.Trim();
                    cameraInfo.CameraFunType = row.GetCell(7).StringCellValue.Trim();
                    cameraInfo.Region = row.GetCell(8).StringCellValue.Trim();
                    cameraInfo.Type = row.GetCell(9).StringCellValue.Trim();
                    cameraInfo.Status = row.GetCell(10).StringCellValue.Trim();
                    cameraInfo.Mac = row.GetCell(11).StringCellValue.Trim();
                    cameraInfo.Ip = row.GetCell(12).StringCellValue.Trim();
                    _cameraList.Add(cameraInfo);
                }
            }

            //過濾數據
            _cameraList = _cameraList.FindAll(cameraInfo =>
            {
                if (!string.IsNullOrWhiteSpace(cameraInfo.Lng) && !string.IsNullOrWhiteSpace(cameraInfo.Lat))
                {
                    double lng = Convert.ToDouble(cameraInfo.Lng);
                    double lat = Convert.ToDouble(cameraInfo.Lat);
                    bool bl = (bool)_engine.Invoke("calc", new object[] { lng, lat, _selectedRegionPoints });
                    if (bl) //區域內
                    {
                        return false;
                    }
                    else //區域外
                    {
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            });

            saveFileDialog1.Title = "選擇處理結果要保存的位置及文件名";
            saveFileDialog1.Filter = "Excel文件(*.xlsx)|*.xlsx";
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                if (File.Exists(saveFileDialog1.FileName))
                {
                    File.Delete(saveFileDialog1.FileName);
                }
                string template = AppDomain.CurrentDomain.BaseDirectory + "點位模板.xlsx";
                XSSFWorkbook workbook;
                using (FileStream fs = new FileStream(template, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    workbook = new XSSFWorkbook(fs);

                    using (FileStream fs2 = new FileStream(saveFileDialog1.FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        ISheet sheet = workbook.GetSheetAt(0);
                        sheet.RemoveRow(sheet.GetRow(1));
                        sheet.RemoveRow(sheet.GetRow(2));
                        Dictionary<int, ICellStyle> cellStyles = GetCellStyles(sheet);
                        int i = 1;
                        foreach (CameraInfo cameraInfo in _cameraList)
                        {
                            IRow row = sheet.CreateRow(i);
                            ICell cell1 = row.CreateCell(1, CellType.String);
                            ICell cell2 = row.CreateCell(2, CellType.String);
                            ICell cell3 = row.CreateCell(3, CellType.String);
                            ICell cell4 = row.CreateCell(4, CellType.String);
                            ICell cell5 = row.CreateCell(5, CellType.String);
                            ICell cell6 = row.CreateCell(6, CellType.String);
                            ICell cell7 = row.CreateCell(7, CellType.String);
                            ICell cell8 = row.CreateCell(8, CellType.String);
                            ICell cell9 = row.CreateCell(9, CellType.String);
                            ICell cell10 = row.CreateCell(10, CellType.String);
                            ICell cell11 = row.CreateCell(11, CellType.String);
                            ICell cell12 = row.CreateCell(12, CellType.String);
                            SetCellStyles(row, cellStyles);
                            cell1.SetCellValue(cameraInfo.CameraNo);
                            cell2.SetCellValue(cameraInfo.City);
                            cell3.SetCellValue(cameraInfo.County);
                            cell4.SetCellValue(cameraInfo.CameraName);
                            cell5.SetCellValue(cameraInfo.Lng);
                            cell6.SetCellValue(cameraInfo.Lat);
                            cell7.SetCellValue(cameraInfo.CameraFunType);
                            cell8.SetCellValue(cameraInfo.Region);
                            cell9.SetCellValue(cameraInfo.Type);
                            cell10.SetCellValue(cameraInfo.Status);
                            cell11.SetCellValue(cameraInfo.Mac);
                            cell12.SetCellValue(cameraInfo.Ip);
                            i++;
                        }
                        workbook.Write(fs2);
                    }
                    MessageBox.Show("完成");
                }
            }
        }

        private Dictionary<int, ICellStyle> GetCellStyles(ISheet sheet)
        {
            var styleRow = sheet.GetRow(5);
            Dictionary<int, ICellStyle> result = new Dictionary<int, ICellStyle>();
            for (int i = 1; i <= 12; i++)
            {
                result.Add(i, styleRow.GetCell(i).CellStyle);
            }
            return result;
        }

        private void SetCellStyles(IRow row, Dictionary<int, ICellStyle> styles)
        {
            for (int i = 1; i <= 12; i++)
            {
                row.GetCell(i).CellStyle = styles[i];
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _engine.Dispose();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.Description = "選擇模板文件保存位置";
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                string template = AppDomain.CurrentDomain.BaseDirectory + "點位模板.xlsx";
                string filePath = Path.Combine(folderBrowserDialog1.SelectedPath, "點位模板.xlsx");
                if (File.Exists(filePath))
                {
                    if (MessageBox.Show("模板文件已存在,是否覆蓋?", "提示", MessageBoxButtons.OKCancel) == DialogResult.OK)
                    {
                        File.Copy(template, filePath, true);
                        MessageBox.Show("下載完成");
                    }
                }
                else
                {
                    File.Copy(template, filePath, true);
                    MessageBox.Show("下載完成");
                }
            }
        }
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 摘要:本文主要講解圖像局部直方圖均衡化和自動色彩均衡化處理。這些演算法可以廣泛應用於圖像增強、圖像去噪、圖像去霧等領域。 本文分享自華為雲社區《[Python從零到壹] 五十四.圖像增強及運算篇之局部直方圖均衡化和自動色彩均衡化處理》,作者: eastmount。 一.局部直方圖均衡化 前文通過調用O ...
  • 簡介 限流顧名思義是對流量大小進行限制,防止請求數量超過系統的負載能力,導致系統崩潰,起到保護作用。 現實生活中限流也隨處可見,節假日出門旅行的人數會劇增,對於旅游景點來說往往會不堪重負,如果不進行人數控制,對整個景點的壓力會非常大,游客的體驗也會非常差,還容易出現安全事故等危險。 同樣的在一線城市 ...
  • 轉載:https://blog.csdn.net/tslx1020/article/details/128250777 1、spawn - 冷啟動 frida-trace -U -f com.apple.ExampleCode -m “+[NSURL URLWithString:]" 2、attac ...
  • 伺服器信息 在阿裡雲買了個搶占式的伺服器,地區為華南廣州,系統為Ubuntu 20.04,8核16GB。 安裝Docker 命令如下: $ apt-get update -y $ apt-get upgrade -y $ apt-get install -y docker.io 安裝成功後,檢查一下 ...
  • 2023-01-14 一、Spring底層IOC實現 1、IOC:將對象的控制器反轉給Spring 2、BeanFactory與ApplicationContext (1)BeanFactory:IOC容器的基本實現,是Spring內部的使用介面,是面向Spring本身的,不是提供給開發人員使用的。 ...
  • 牛牛剛剛出生,嗷嗷待哺,一開始他只能學說簡單的數字,你跟他說一個整數,他立刻就能學會。輸入一個整數,輸出這個整數。 ...
  • 本篇文章,我們就一起聊一聊如何來更好的使用緩存,探尋下如何降低緩存交互過程的性能損耗、如何壓縮緩存的存儲空間占用、如何保證多個操作命令原子性等問題的解決策略,讓緩存在項目中可以發揮出更佳的效果。 ...
  • C++11 智能指針 shared_ptr Written on 2023-01-16 個人學習智能指針記錄合集: C++11 智能指針 C++11 智能指針 shared_ptr C++11 智能指針 unique_ptr C++11 智能指針 weak_ptr std::shared_ptr 共 ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...