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
  • 下麵是一個標準的IDistributedCache用例: public class SomeService(IDistributedCache cache) { public async Task<SomeInformation> GetSomeInformationAsync (string na ...
  • 這個庫提供了在啟動期間實例化已註冊的單例,而不是在首次使用它時實例化。 單例通常在首次使用時創建,這可能會導致響應傳入請求的延遲高於平時。在註冊時創建實例有助於防止第一次Request請求的SLA 以往我們要在註冊的時候實例單例可能會這樣寫: //註冊: services.AddSingleton< ...
  • 最近公司的很多項目都要改單點登錄了,不過大部分都還沒敲定,目前立刻要做的就只有一個比較老的項目 先改一個試試手,主要目標就是最短最快實現功能 首先因為要保留原登錄方式,所以頁面上的改動就是在原來登錄頁面下加一個SSO登錄入口 用超鏈接寫的入口,頁面改造後如下圖: 其中超鏈接的 href="Staff ...
  • Like運算符很好用,特別是它所提供的其中*、?這兩種通配符,在Windows文件系統和各類項目中運用非常廣泛。 但Like運算符僅在VB中支持,在C#中,如何實現呢? 以下是關於LikeString的四種實現方式,其中第四種為Regex正則表達式實現,且在.NET Standard 2.0及以上平... ...
  • 一:背景 1. 講故事 前些天有位朋友找到我,說他們的程式記憶體會偶發性暴漲,自己分析了下是非托管記憶體問題,讓我幫忙看下怎麼回事?哈哈,看到這個dump我還是非常有興趣的,居然還有這種游戲幣自助機類型的程式,下次去大玩家看看他們出幣的機器後端是不是C#寫的?由於dump是linux上的程式,剛好win ...
  • 前言 大家好,我是老馬。很高興遇到你。 我們為 java 開發者實現了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何處理的,可以參考我的另一個項目: 手寫從零實現簡易版 tomcat minicat 手寫 ngin ...
  • 上一次的介紹,主要圍繞如何統一去捕獲異常,以及為每一種異常添加自己的Mapper實現,並且我們知道,當在ExceptionMapper中返回非200的Response,不支持application/json的響應類型,而是寫死的text/plain類型。 Filter為二方包異常手動捕獲 參考:ht ...
  • 大家好,我是R哥。 今天分享一個爽飛了的面試輔導 case: 這個杭州兄弟空窗期 1 個月+,面試了 6 家公司 0 Offer,不知道問題出在哪,難道是杭州的 IT 崩盤了麽? 報名面試輔導後,經過一個多月的輔導打磨,現在成功入職某上市公司,漲薪 30%+,955 工作制,不咋加班,還不捲。 其他 ...
  • 引入依賴 <!--Freemarker wls--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency> ...
  • 你應如何運行程式 互動式命令模式 開始一個互動式會話 一般是在操作系統命令行下輸入python,且不帶任何參數 系統路徑 如果沒有設置系統的PATH環境變數來包括Python的安裝路徑,可能需要機器上Python可執行文件的完整路徑來代替python 運行的位置:代碼位置 不要輸入的內容:提示符和註 ...