C# WinForm 使用SMS接口发送手机验证码+图形验证码+IP限制

article/2025/8/27 19:30:35

文章目录

  • 前言
  • 功能实现
    • 一、功能界面
    • 二、创建图形验证码类
    • 三、创建存储IP地址的数据库表
    • 四、创建手机验证码类
    • 五、在Form1中调用以上两个类中的函数,实现功能


前言

  1.发送手机验证码用的是网建的SMS接口(http://sms.webchinese.cn/)
  2.手机验证码简单的做了以下限制:
    ①发送验证码1分钟只能点击发送1次
    ②相同IP手机号码1天最多提交20次(这里我用的是本地局域网IP)
    ③加入图形验证码
  注:SMS官网上的建议还有要对手机号码次数进行限制:单个手机号码30分钟最多提交10次。(这个和IP限制次数方法是一样的,我这里没加)


功能实现

一、功能界面

在这里插入图片描述

二、创建图形验证码类

关于图形验证码,也可以参照我的这篇文章:C# WinForm 登录界面的图片验证码

创建产生图形验证码的类:
  ①生成随机验证码字符串,用的是Random随机函数,用GUID生成6位随机数
  ②创建验证码图片,将该字符串画在PictureBox控件中

ImageVeriCodeClass:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;//绘图
using System.Windows.Forms;namespace SMSVeriCode
{public class ImageVeriCodeClass{#region 图片验证码功能            /// <summary>/// 生成随机验证码字符串/// </summary>public static string CreateRandomImageCode(int CodeLength){int randNum;char code;string randomCode = String.Empty;//随机验证码//生成一定长度的随机验证码       //Random random = new Random();//生成随机数对象for (int i = 0; i < CodeLength; i++){//利用GUID生成6位随机数      byte[] buffer = Guid.NewGuid().ToByteArray();//生成字节数组int seed = BitConverter.ToInt32(buffer, 0);//利用BitConvert方法把字节数组转换为整数Random random = new Random(seed);//以生成的整数作为随机种子randNum = random.Next();//randNum = random.Next();                if (randNum % 3 == 1){code = (char)('A' + (char)(randNum % 26));//随机大写字母}else if (randNum % 3 == 2){code = (char)('a' + (char)(randNum % 26));//随机小写字母}else{code = (char)('0' + (char)(randNum % 10));//随机数字}randomCode += code.ToString();}return randomCode;}/// <summary>/// 创建验证码图片/// </summary>public static void CreateImage(string strValidCode, PictureBox pbox){try{int RandAngle = 45;//随机转动角度int MapWidth = (int)(strValidCode.Length * 21);Bitmap image = new Bitmap(MapWidth, 28);//验证码图片大小-宽和高//创建绘图对象GraphicsGraphics graph = Graphics.FromImage(image);graph.Clear(Color.AliceBlue);//清除绘画面,填充背景色graph.DrawRectangle(new Pen(Color.Black, 0), 0, 0, image.Width - 1, image.Height - 1);//画一个边框graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;//模式Random rand = new Random();//背景噪点生成Pen blackPen = new Pen(Color.LightGray, 0);for (int i = 0; i < 50; i++){int x = rand.Next(0, image.Width);int y = rand.Next(0, image.Height);graph.DrawRectangle(blackPen, x, y, 1, 1);}//验证码旋转,防止机器识别char[] chars = strValidCode.ToCharArray();//拆散字符串成单字符数组//文字居中StringFormat format = new StringFormat(StringFormatFlags.NoClip);format.Alignment = StringAlignment.Center;format.LineAlignment = StringAlignment.Center;//定义颜色Color[] c = { Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple };//定义字体string[] font = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" };for (int i = 0; i < chars.Length; i++){int cindex = rand.Next(7);int findex = rand.Next(5);Font f = new System.Drawing.Font(font[findex], 13, System.Drawing.FontStyle.Bold);//字体样式(参数2为字体大小)Brush b = new System.Drawing.SolidBrush(c[cindex]);Point dot = new Point(16, 16);float angle = rand.Next(-RandAngle, RandAngle);//转动的度数graph.TranslateTransform(dot.X, dot.Y);//移动光标到指定位置graph.RotateTransform(angle);graph.DrawString(chars[i].ToString(), f, b, 1, 1, format);graph.RotateTransform(-angle);//转回去graph.TranslateTransform(2, -dot.Y);//移动光标到指定位置}pbox.Image = image;}catch (ArgumentException){MessageBox.Show("验证码图片创建错误");}}#endregion}
}

三、创建存储IP地址的数据库表

对于IP次数的限制,我是把IP地址存在了数据库的表里。

①先创建一个数据库SMSVeriCode
②创建tIP表的sql语句:

create table tIP
(IP nvarchar(32), --IP地址SendTimes int, --发送次数SMSVeriCodeTime datetime2 --手机验证码发送时间
)

在这里插入图片描述


四、创建手机验证码类

创建发送手机验证码的类:
  ①发送手机验证码功能
  ②验证国内手机号
  ③根据IP地址限制手机号码1天最多提交20次
  ④获取本地IP地址信息(局域网IP)

SMSVeriCodeClass:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
//需要用到的命名空间
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Data.SqlClient;
using System.Net.Sockets;namespace SMSVeriCode
{public class SMSVeriCodeClass{#region  手机验证码功能/// <summary>///  获取随机验证码///   利用GUID获取随机数/// </summary>/// <param name="Phone">手机号</param>/// <param name="MinSeed">随机数最小值</param>/// <param name="MaxSeed">随机数最大值</param>/// <returns>随机验证码</returns>public static string GetSMSValidCode(int MinSeed, int MaxSeed){byte[] pbyte = Guid.NewGuid().ToByteArray();//生成字节数组int seed = BitConverter.ToInt32(pbyte, 0);//利用BitConvert方法把字节数组转换为整数Random random = new Random(seed);//以生成的整数作为随机种子string smsVeriCode = random.Next(MinSeed, MaxSeed).ToString();return smsVeriCode;}/// <summary>///  发送验证码的函数/// </summary>/// <param name="Phone"></param>/// <param name="textContent"></param>/// <returns>返回发送的结果:数字</returns>public static string SendSMSVeriCode(string UidName, string KeyMD5, string Phone, string TextContent){string strUrl = "http://utf8.sms.webchinese.cn/?";//UTF-8编码Urlstring strUidName = "Uid=";//SMS平台的用户名string strKeyMD5 = "&key=";//SMS平台的接口密匙;strKeyMD5=接口密钥32位MD5加密(大写)string strPhone = "&smsMob=";//目的手机号码string strTextContent = "&smsText="; //短信内容;普通短信70个字/条strUrl = strUrl + strUidName + UidName + strKeyMD5 + KeyMD5 + strPhone + Phone + strTextContent + TextContent;string SMSResult = GetFromUrl(strUrl);//发送短信,得到返回值//MessageBox.Show(Result);//string JudgeResult = GetResult(SMSResult);//判断返回值             //return JudgeResult;return SMSResult;}/// <summary>/// 发送短信,得到返回值/// </summary>       public static string GetFromUrl(string url){string strReturn = null;if (url == null || url.Trim().ToString() == ""){return strReturn;}else//手机号正确{string targeturl = url.ToString();try{HttpWebRequest hr = (HttpWebRequest)WebRequest.Create(targeturl);hr.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";hr.Method = "GET";hr.Timeout = 30 * 60 * 1000; //30分钟超时WebResponse hs = hr.GetResponse();Stream sr = hs.GetResponseStream();StreamReader ser = new StreamReader(sr, Encoding.Default);strReturn = ser.ReadToEnd();}catch (Exception ex){strReturn = null;MessageBox.Show(ex.Message);}}return strReturn;}/// <summary>/// 判断返回值 /// </summary>      public static string GetResult(string strReturn){int result = 0;try{result = int.Parse(strReturn);switch (result){case -1:strReturn = "没有该用户账户";break;case -2:strReturn = "接口密钥不正确,不是账户登陆密码";break;case -21:strReturn = "MD5接口密钥加密不正确";break;case -3:strReturn = "短信数量不足";break;case -11:strReturn = "该用户被禁用";break;case -14:strReturn = "短信内容出现非法字符";break;case -4:strReturn = "手机号格式不正确";break;case -41:strReturn = "手机号码为空";break;case -42:strReturn = "短信内容为空";break;case -51:strReturn = "短信签名格式不正确,接口签名格式为:【签名内容】";break;case -52:strReturn = "短信签名太长";break;case -6:strReturn = "IP限制";break;default:strReturn = "成功发送" + result + "条短信!";break;}}catch (Exception ex){strReturn = ex.Message;}return strReturn;}#endregion/// <summary>/// 验证国内手机号/// </summary>/// <param name="phone">手机号</param>/// <returns></returns>public static bool CheckMobilePhone(string phone){//电信手机号码正则        string dianxin = @"^1[3578][01379]\d{8}$";Regex dReg = new Regex(dianxin);//联通手机号正则        string liantong = @"^1[34578][01256]\d{8}$";Regex tReg = new Regex(liantong);//移动手机号正则        string yidong = @"^(134[012345678]\d{7}|1[34578][012356789]\d{8})$";Regex yReg = new Regex(yidong);if (dReg.IsMatch(phone) || tReg.IsMatch(phone) || yReg.IsMatch(phone)){return true;}return false;}#region  根据IP限制手机号码1天最多提交20次    /// <summary>///  发送次数清零/// </summary>         public static int ResetSendTimes(string IP){string connString = "server=.;database=SMSVeriCode;uid=test;pwd=test";SqlConnection pSqlConnection = new SqlConnection(connString);pSqlConnection.Open();string sqlReset = "update tIP set SendSMSTimes=0 where IP='" + IP + "'";SqlCommand sqlcmdReset = new SqlCommand(sqlReset, pSqlConnection);return sqlcmdReset.ExecuteNonQuery();}/// <summary>///  更新已发送的次数/// </summary>       public static int UpdateSendTimes(string IP){string connString = "server=.;database=SMSVeriCode;uid=test;pwd=test";SqlConnection pSqlConnection = new SqlConnection(connString);pSqlConnection.Open();string sqlUdpate = "update tIP set SendSMSTimes = SendSMSTimes + 1 where IP='" + IP + "'";SqlCommand sqlcmdUpdate = new SqlCommand(sqlUdpate, pSqlConnection);return sqlcmdUpdate.ExecuteNonQuery();}/// <summary>///  更新手机验证码发送时间/// </summary>     public static int UpdateSMSCodeTime(string IP){string connString = "server=.;database=SMSVeriCode;uid=test;pwd=test";SqlConnection pSqlConnection = new SqlConnection(connString);pSqlConnection.Open();string sqlUpdateTime = "update tIP set SMSVeriCodeTime=getdate() where IP='" + IP + "'";SqlCommand sqlcmdUpdateTime = new SqlCommand(sqlUpdateTime, pSqlConnection);return sqlcmdUpdateTime.ExecuteNonQuery();}#endregion   /// <summary>/// 获取本地IP地址信息/// </summary>public static string GetLocalIP(){try{string HostName = Dns.GetHostName();//主机名IPHostEntry ip = Dns.GetHostEntry(HostName);for (int i = 0; i < ip.AddressList.Length; i++){//AddressFamily.InterNetwork表示IPV4//AddressFamily.InterNetworkV6表示IPV6if (ip.AddressList[i].AddressFamily == AddressFamily.InterNetwork){return ip.AddressList[i].ToString();}}return "";}catch (Exception ex){MessageBox.Show("GetLocalIP Error!" + ex.Message);return "";}}}
}

五、在Form1中调用以上两个类中的函数,实现功能

注:
  以下代码中的"用户名"和"密钥",要去SMS网站中查看。

string UidName = "XXXXXXX";//SMS平台的用户名
string KeyMD5 = "XXXXXXXX";//SMS平台的接口密匙;

IP次数限制的大致思路——相同IP手机号码1天最多提交20次:
  ①用户发送验证码,获取其IP地址,判断数据表中是否已经有了这个IP;
  如果没有就向数据表中插入这个新的IP地址,接着发送验证码,在表中更新发送次数+1;
  ②如果查询到表中已经有了这个IP地址,就判断其是否满足条件(发送次数<=20,时间<24小时);
  ③如果不满足条件,直接返回,不往下继续执行程序;
  ④如果满足条件,往下执行程序,发送验证码。(同时要注意查询表中的发送次数是否为0,要更新发送时间)

Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace SMSVeriCode
{public partial class Form1 : Form{public Form1(){InitializeComponent();}#region 图片验证码                private const int ImageVeriCodeLength = 4;//验证码长度        private String strImageVeriCode = "";//验证码           //更新图片验证码private void UpdateImageVeriCode(){strImageVeriCode = ImageVeriCodeClass.CreateRandomImageCode(ImageVeriCodeLength);//生成随机验证码if (strImageVeriCode == "") return;ImageVeriCodeClass.CreateImage(strImageVeriCode, pbox1);//创建验证码图片}#endregion//窗体加载时更新图片验证码private void Form1_Load(object sender, EventArgs e){UpdateImageVeriCode();}//点击PictureBox更新图片验证码private void pbox1_Click(object sender, EventArgs e){UpdateImageVeriCode();}/// <summary>///  获取手机验证码/// </summary>int seconds1 = 60;//倒计时60sint seconds2 = 60 * 5;//验证码有效时间5分钟string strSMSVeriCode;    private void btnSendVeriCode_Click(object sender, EventArgs e){//获取文本框中的数据string phone = txtPhone.Text.Trim();//手机号string imagevericode = txtImageVeriCode.Text.Trim();//图片验证码                                    strSMSVeriCode = SMSVeriCodeClass.GetSMSValidCode(100000, 999999);//随机6位SMS验证码int totalTime = 5;//SMS验证码有效时长string smsTextContent = "验证码:" + strSMSVeriCode + "," + totalTime + "分钟内有效,请勿泄漏于他人。如非本人操作,请忽略。";//SMS短信文本内容            string UidName = "XXXXXXX";//SMS平台的用户名string KeyMD5 = "XXXXXXXX";//SMS平台的接口密匙;            if (String.IsNullOrEmpty(phone))//判断是否输入了手机号{MessageBox.Show("请输入手机号!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);txtPhone.Focus();                }else if (SMSVeriCodeClass.CheckMobilePhone(phone) == false)//判断手机号格式是否正确{MessageBox.Show("请输入有效的11位手机号码", "警告", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);                txtPhone.Focus();}else if (String.IsNullOrEmpty(imagevericode))//判断是否输入了图片验证码{MessageBox.Show("请输入图片验证码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);txtImageVeriCode.Focus();}else if (imagevericode.ToLower() != strImageVeriCode.ToLower())//判断图片验证码输入是否正确;不区分大小写{MessageBox.Show("您输入的验证码有误!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);UpdateImageVeriCode();txtImageVeriCode.Text = "";txtImageVeriCode.Focus();}else//发送SMS验证码{string ip = SMSVeriCodeClass.GetLocalIP();string connString = "server=.;database=SMSVeriCode;uid=test;pwd=test";SqlConnection pSqlConnection = new SqlConnection(connString);pSqlConnection.Open();string sqlIP = "select *,datediff(hour,SMSVeriCodeTime,getdate()) as TimeIntervel from tIP where IP='" + ip + "'";SqlCommand sqlcmdIP = new SqlCommand(sqlIP, pSqlConnection);SqlDataReader sdr = sqlcmdIP.ExecuteReader();sdr.Read();if (sdr.HasRows == true)//表中已有此IP地址{if (sdr.GetInt32(1) == 20 && sdr.GetInt32(3) <= 24)//20次,24小时{MessageBox.Show("相同IP手机号码1天最多提交20次!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);UpdateImageVeriCode();txtImageVeriCode.Text = "";return;}                  else if (sdr.GetInt32(1) == 20 && sdr.GetInt32(3) > 24){SMSVeriCodeClass.ResetSendTimes(ip);//发送次数置零}if (sdr.GetInt32(1) == 0)//次数为0时{string SMSResult = SMSVeriCodeClass.SendSMSVeriCode(UidName, KeyMD5, phone, smsTextContent);//发送                                if (Convert.ToInt32(SMSResult) > 0)//成功发送SMS验证码{//倒计时开始timer1.Interval = 1000;timer1.Start();timer2.Interval = 1000;timer2.Start();btnSendVeriCode.Enabled = false;UpdateImageVeriCode();txtImageVeriCode.Text = "";SMSVeriCodeClass.UpdateSendTimes(ip);//更新发送次数+1SMSVeriCodeClass.UpdateSMSCodeTime(ip);//更新发送时间}else//发送SMS验证码失败{string JudetResult = SMSVeriCodeClass.GetResult(SMSResult);MessageBox.Show(JudetResult, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);}}else{string SMSResult = SMSVeriCodeClass.SendSMSVeriCode(UidName, KeyMD5, phone, smsTextContent);//发送                                if (Convert.ToInt32(SMSResult) > 0)//成功发送SMS验证码{//倒计时开始timer1.Interval = 1000;timer1.Start();timer2.Interval = 1000;timer2.Start();btnSendVeriCode.Enabled = false;UpdateImageVeriCode();txtImageVeriCode.Text = "";SMSVeriCodeClass.UpdateSendTimes(ip);//更新发送次数+1                        }else//发送SMS验证码失败{string JudetResult = SMSVeriCodeClass.GetResult(SMSResult);MessageBox.Show(JudetResult, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);}}                    }else//表中没有此IP地址—第一次发送验证码{string smsSendTime = DateTime.Now.ToString();//SMS验证码发送时间//--------向数据表tIP中添加信息------//pSqlConnection.Close();pSqlConnection.Open();                    string sqlInsert = "insert into tIP(IP,SendSMSTimes,SMSVeriCodeTime)";sqlInsert += "values('{0}','{1}','{2}')";sqlInsert = string.Format(sqlInsert, ip,"0",smsSendTime);SqlCommand sqlcmdInsert = new SqlCommand(sqlInsert, pSqlConnection);sqlcmdInsert.ExecuteNonQuery();//--------------发送验证码----------------//     string SMSResult = SMSVeriCodeClass.SendSMSVeriCode(UidName, KeyMD5, phone, smsTextContent);//发送                                if (Convert.ToInt32(SMSResult) > 0)//成功发送SMS验证码{//倒计时开始timer1.Interval = 1000;timer1.Start();timer2.Interval = 1000;timer2.Start();btnSendVeriCode.Enabled = false;UpdateImageVeriCode();txtImageVeriCode.Text = "";SMSVeriCodeClass.UpdateSendTimes(ip);//更新发送次数+1                        }else//发送SMS验证码失败{string JudetResult = SMSVeriCodeClass.GetResult(SMSResult);MessageBox.Show(JudetResult, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);}}}}/// <summary>///  倒计时—SMS验证码1分钟只能点击发送1次/// </summary>       private void timer1_Tick(object sender, EventArgs e){if (seconds1 > 0){seconds1--;btnSendVeriCode.Text = "剩余" + seconds1.ToString() + "秒";}else{timer1.Stop();btnSendVeriCode.Text = "获取验证码";btnSendVeriCode.Enabled = true;}}/// <summary>///  手机SMS验证码5分钟内有效;但是如果有新的验证码出现,旧验证码就会失效        /// </summary>private void timer2_Tick(object sender, EventArgs e){if (seconds2 == 0){timer2.Stop();//旧的验证码过期,生成一个新的验证码strSMSVeriCode = SMSVeriCodeClass.GetSMSValidCode(100000, 999999);}}/// <summary>///  确认按钮/// </summary>  private void btnConfirm_Click(object sender, EventArgs e){//获取文本数据string smsvericode = txtSMSVeriCode.Text.Trim();//手机SMS验证码if (String.IsNullOrEmpty(smsvericode)){MessageBox.Show("请输入手机验证码!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);txtSMSVeriCode.Focus();}else if (smsvericode != strSMSVeriCode)//判断手机SMS验证码是否输入正确{MessageBox.Show("您输入的验证码有误!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);txtSMSVeriCode.Focus();}else{MessageBox.Show("验证成功!");}}        }
}

http://chatgpt.dhexx.cn/article/hqXQmmIP.shtml

相关文章

uniapp | 发送手机验证码 button组件

一、功能和效果展示 1.组件功能 uniapp &#xff08;1&#xff09;按钮初始显示“发送”&#xff0c;点击按钮后按钮显示倒计时60s&#xff1b; &#xff08;2&#xff09;倒计时60s期间点击按钮&#xff0c;不会重置计时器&#xff1b; &#xff08;3&#xff09;倒计时60s结…

发送手机验证码

手机验证码不能自己生成&#xff0c;需要由第三方来完成发送。本文选择网易云作为第三方来发送验证码。 首先&#xff0c;我们要注册网易云账号&#xff0c;完成登陆。选择“产品与服务”选项中的“通信与视频”&#xff0c;点击创建应用&#xff0c;完成后&#xff0c;下方有…

java发送手机验证码实现

正文 今天来用java实现手机验证码的发送。 短信平台有很多&#xff0c;中国网建提供的SMS短信通&#xff0c;注册免费5条短信&#xff0c;3条彩信&#xff0c; http://sms.webchinese.cn/ 但是刚才试了&#xff0c;第一次用官方提供的demo发送成功&#xff0c;然后整合到自…

Excel 字符串拼接

例子&#xff1a;“exec sp_addextendedproperty N’MS_Description’, N’”&B1&“‘, N’SCHEMA’, N’dbo’,N’table’, N’”&A1&“” &#xff1a;公式 “ abc ” &#xff1a; “”中间为任意字符/字符串 & A1 &&#xff1a;&&中间为拼…

Excel如何插入文本字符串或字符

目录 1.用“&”连接的方法插入文本或字符的办法及实例 2.用TEXT函数插入“&#xffe5;”或“$"字符 3.用TEXT函数以及“&”连接符插入文本或符号 1.用“&”连接的方法插入文本或字符的办法及实例 &#xff08;1&#xff09;方法&#xff1a;关键在于用“&a…

excel连接字符串

Excel连接字符串的功能挺强大的。 很实用。 有2种方式。 1&#xff1a; 2&#xff1a; 1个是调用了concatnate函数&#xff0c;一个是使用了&(就是号的功能了)。

excel字符串和单元格拼接,Excel中将单元格的字符串进行合并的具体方法

在利用Excel进行办公时&#xff0c;对多个单元格的字符串进行合并是很常见的操作&#xff0c;但是对于刚接触Excel软件的小伙伴来说&#xff0c;可能有些困难。下面小编就与大家分享一下在Excel中实现字符串合并的方法&#xff0c;有需要的用户可以参考下。 Excel中如何合并文本…

excel中按条件合并字符串

若B列不为空则将A列和B列合并后给C列&#xff1b; C IF(ISBLANK(B1), B1,CONCAT(A1,B1)) 结果却出问题&#xff0c;当B列为空时&#xff0c;C列却显示0&#xff0c;解决方法是&#xff1a;选择C列设置单元格格式&#xff0c;选择自定义&#xff0c;在类型处添加 [0]" &q…

Excel技巧:巧用字符串连接

Excel中有一个基本的公式&#xff0c;就是把几个单元格中的字符串连接起来。 比如上面这个例子&#xff0c;A1&#xff0c;B1&#xff0c;C1单元格中字符串连接起来&#xff0c;只要在D1单元格中输入 A1&B1&C1即可。 下面我们开始使用字符串连接功能。 例1&#xff1a;…

Excel字符连接(concat)

Excel连接字符串有两个比较常用的方法。 1.concat函数 2.”&”连接符

C#操作Excel文件三种方式及连接字符串

转自&#xff1a;http://www.cnblogs.com/JacobHuang/p/5663926.html .Net平台上对Excel进行操作主要有两种方式。第一种&#xff0c;把Excel文件看成一个数据库&#xff0c;通过OleDb的方式进行读取与操作&#xff1b;第二种&#xff0c;调用Excel的COM组件。两种方式各有特点…

EXCEL 连接符的简单使用

在使用EXCEL处理大量表格数据的时候&#xff0c;学会【连接符】的使用很重要。 如下图所示&#xff1a; 如果我们需要在【A列】的内容后面加两个字【“编号”】两个字&#xff0c;我们就可以使用【连接符“&”】。 1&#xff1a;在B列的此处输入【】。 2&#xff1a;选中【…

Excel连接文本字符串

Excel连接文本字符串 一&#xff1a;CONCATENATE 1&#xff09;使用 CONCATENATE 函数。在这种情况下&#xff0c;您的公式将如下所示。其中X1、X2 和 X3 是你要加入的单元格。 CONCATENATE(X1,X2,X3)2&#xff09;如果要用空格分隔单元格的值&#xff0c;可以将它们添加在引…

STM32开发入门

stm32f407系列单片机基础知识 参考stc公司标准开发手册 STM32F4xx中文参考手册1.pdf ##本文是基于stm32f407zgt6单片机做出介绍 stm32系列单片机是stc公司开发并设计出的一类高速低功耗芯片&#xff0c;其具有众多可用内部资源&#xff0c;在下文将一一介绍 芯片实物图 内部资…

Structured Streaming 快速入门系列(三)Structured Streaming 实战之 Sink

文章目录 SinkHDFS SinkKafka SinkForeach Writer自定义 SinkTigger从 Source 到 Sink 的流程错误恢复和容错语义 Sink 目标和步骤 目标 能够串联两端, 理解整个流式应用, 以及其中的一些根本的原理, 比如说容错语义能够知道如何对接外部系统, 写入数据 步骤 HDFS SinkKaf…

STM32基础入门学习笔记:内部高级功能应用

文章目录&#xff1a; 一&#xff1a;低功耗模式 1.睡眠模式测试程序 NVIC.h NVIC.c key.h key.c main.c 2.停机模式测试程序 main.c 3.待机模式测试程序 main.c 二&#xff1a;看门狗 1.独立看门狗测试程序 iwdg.h iwdg.c main.c 2.窗口看门狗测试程序 wwdg…

STM32初学者入门FreeRTOS操作系统,多任务实时系统

1.详细介绍FreeRTOS操作系统&#xff0c;然后举了几个实例 FreeRTOS&#xff08;Free Real-Time Operating System&#xff09;是一个开源的嵌入式实时操作系统&#xff0c;它专门设计用于在资源有限的嵌入式系统中运行。FreeRTOS提供了一些用于任务管理、调度、同步和通信的功…

【STM32系列汇总】博主的STM32实战快速进阶之路(持续更新)

我把之前在学习和工作中使用STM32进行嵌入式开发的经验和教程等相关整理到这里&#xff0c;方便查阅学习&#xff0c;如果能帮助到您&#xff0c;请帮忙点个赞&#xff1b; 本文的宗旨 STM32 只是一个硬件平台&#xff0c;同样地他可以换成MSP430&#xff0c;NXP的RT等等&…

<STC32G12K128入门第四节>USAT串口(实战使用ESP32进行TCP通信)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、串口是什么?二、UART寄存器1.引脚配置寄存器2.SCON寄存器3.SBUF数据发送接收缓冲区4.辅助寄存器5.串口重定向三、案例总结前言 一、串口是什么? 这个我不想多说就是一种通讯方式,想具体…

STM32入门(二)

STM32入门&#xff08;二&#xff09; 一、新建工程 二、库开发与寄存器开发的关系 固件库就是函数的集合&#xff0c;固件库函数的作用是向下负责与寄存器直接打交道&#xff0c;向上提供用户函数调用的接口&#xff08;API&#xff09;。在51的开发中我们常常的作法是直接操…