Win7、Win10共享打印机设置的一次实践

办公室新增了一台打印机,准备把它装在某台电脑上,然后共享给其他人。

1、打印服务器(主机)端设置

安装完成后,在打印机管理界面,设置打印机共享(IP地址为192.168.1.4,打印机共享名为printer),完成后发现其他电脑无法找到该打印机,即使通过UNC路径(\\192.168.1.4\printer)也不行。

解决方案:
1、打开“控制面板”、“网络和共享中心”;
2、选择“更改高级共享设置”;
3、分别对“家庭和工作”网络、“公用”网络设置“启用网络发现”、“启用文件和打印机共享”、“关闭密码保护共享”。

2、客户端设置

设置完成后,有一台安装了Win10的电脑通过在资源管理器地址栏访问“\\192.168.1.4\\printer”,能够看到printer打印机的图标,在图标上点右键选择“连接”,然后安装成功。

另一台安装了Win7的电脑通过“控制面板”、“设备和打印机”界面中的“添加打印机”、“添加网络打印机”、“按名称选择共享打印机”,然后输入“\\192.168.1.4\printer”添加成功。

还有一台安装了Win10的电脑,使用以上两种方法都会提示要输入用户名密码登录。

解决方案:
1、运行“regedit”打开注册表编辑器,依次展开“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters”;
2、找到“AllowInsecureGuestAuth”,设置其值为“1”;
3、如果没有,就新建一个DWORD(32)项“AllowInsecureGuestAuth”,设置其值为“1”;
4、通过资源管理器地址栏访问“\\192.168.1.4\\printer”,提示输入用户名密码窗口中,用户名输入“guest”,密码不用输,确定;
5、安装成功。

经测试,可以打印。

总结:Windows 7和Windows 10对于安全性的重视程度大大增加了,许多对外的功能、接口、权限默认都是关闭的,需要手动设置将其打开。另外,本文中只涉及本次实践操作中遇到的情况,后续若有其他新的情况,届时再另行更新补充。

UPDATE:[20200109]
第二天,发现所有人都无法打印。在打印服务器(宿主机)上,运行“services.msc”打开服务,找到“print spooler”服务,发现服务是关闭状态,将其开启即可。

Word大纲转成PPT的一次实践

最近遇到一个问题,使用Word编辑了一个长文档,包含三级标题,其中一章的内容比较复杂,层次也很分明:一级标题下有十几个二级标题,每个二级标题下都有三到六个左右的三级标题。因为需要给客户做PPT演示,所以要把这一章的内容按照大纲的架构复制到PPT中去。

1、开始在Word大纲视图中直接复制,到PPT大纲视图中粘贴,以为Office组件之间会自动转换,谁知直接卡死,等了很久终于缓过来,发现此操作把整个章节的文字都复制到了一张幻灯片中,完全不符合要求。

2、接下来,在Word文件菜单的选项、自定义功能区中,找到了“发送到PowerPoint”选项,大喜,觉得这下没问题了。将该按钮添加到菜单,点击,提示大纲太长,只转换了一部分,转换出来的结果也不尽如人意,只有从Word文档起始位置开始的很少的一部分文字。

3、接下来,把其他章节的内容全部删掉,只保留需要转换的章节,发送到PPT之后,效果依然不佳,依然提示大纲太长。转换出的结果有大量的正文文字。

4、分析了一下,应该是是正文文字太多的原因,使用Word选择功能,选择所有格式类似的文本,然后一下子将所有正文全部删除。再发送到PPT,发现该操作把所有的二级标题都尽可能压缩在了一张幻灯片中,实在放不下了,才会换到下一张,一百多行内容挤压在三张幻灯片中。

5、分析了一下,感觉应该是大纲级别的原因。于是使用Word的替换功能,把二级标题样式替换为一级标题,再把三级标题样式替换为二级标题。然后再进行发送到PPT操作,就得到了想要的结果,每个原二级标题一张幻灯片,原二级标题位于标题区域,每张幻灯片的内容区域则是原三级标题的列表。

总结:Word文档的排版最好能着眼全局,级别相同的文本或标题要使用一致的样式,这样在对全文进行总体上的一些布局设置的时候,就非常方便。
知识点:Word可以把大纲直接发送到PPT;Word可以直接替换标题样式;Word可以选择所有格式类似的文本。

SQL如何增删查改字段值为null的记录

数据库中建表的时候,允许某些字段为空可以简化很多操作,但是,字段为空(null)值,在增(insert)删(delete)查(select)改(update)操作时,所使用的运算符或表达式还是不完全一样的。

插入字段值为null的记录

insert插入操作如果要插入一条记录,其中的某些字段值是null,有两种方法。一种是直接忽略该字段,一种是直接插入null值。注意不要写成’null’,因为null是一个特定的值,不是一个字符串。

假设User表有Id、Name、Age、City四个字段,如果要插入一条City字段值为null的记录:

1
2
3
4
5
/** 1、直接忽略City字段 **/
INSERT INTO USER (Id, Name, Age) VALUES ('0003', '张三', 29)

/** 2、设置该字段值为null **/
INSERT INTO USER (Id, Name, Age, City) VALUES ('0003', '张三', 29, NULL)

删除字段值为null或不为null的记录

delete删除操作如果要删除记录,条件时某些字段是null或者不是null,要通过“字段名 is null”或者“字段名 is not null”来判断,不能使用“字段名 = null”判断。

假设User表有Id、Name、Age、City四个字段,如果要删除所有City字段值为null的记录:

1
2
3
4
5
/** 1、使用City = null,执行后影响的记录条数为0 **/
DELETE USER WHERE City = NULL

/** 2、使用City is null,执行后所有City字段为null的记录被删除 **/
DELETE USER WHERE City IS NULL

假设User表有Id、Name、Age、City四个字段,如果要删除所有City字段值不为null的记录:

1
2
3
4
5
/** 1、使用City <> null,执行后影响的记录条数为0 **/
DELETE USER WHERE City = NULL

/** 2、使用City is not null,执行后所有City字段不为null的记录被删除 **/
DELETE USER WHERE City IS NOT NULL

查询字段值为null或者不为null的记录

select查询操作如果要查询记录,条件时某些字段是null或者不是null,要通过“字段名 is null”或者“字段名 is not null”来判断,不能使用“字段名 = null”判断。

假设User表有Id、Name、Age、City四个字段,如果要查询所有City字段值为null的记录:

1
2
3
4
5
/** 1、使用City = null,执行后影响的记录条数为0 **/
SELECT * FROM USER WHERE City = NULL

/** 2、使用City is null,执行后所有City字段为null的记录被列出 **/
SELECT * FROM USER WHERE City IS NULL

假设User表有Id、Name、Age、City四个字段,如果要查询所有City字段值不为null的记录:

1
2
3
4
5
/** 1、使用City <> null,执行后影响的记录条数为0 **/
SELECT * FROM USER WHERE City = NULL

/** 2、使用City is not null,执行后所有City字段不为null的记录被删除 **/
SELECT * FROM USER WHERE City IS NOT NULL

修改记录的字段值为null

update更新操作如果要更新记录,将记录的某个字段设置为null值,要直接设置“字段名=null”,而非“字段名 is null”。

假设User表有Id、Name、Age、City四个字段,如果要修改Id为“0001”的记录的City字段值为null:

1
2
3
4
5
/** 1、使用City is null,执行后SQL Server会报错,提示有语法错误 **/
UPDATE USER SET City IS NULL WHERE Id = '0001'

/** 2、使用City = null,执行后Id为“0001”的记录的City字段值被改为null **/
UPDATE USER SET City = NULL WHERE Id = '0001'

总结

综上,对null字段的操作,什么时候用“=”符号,什么时候用“is”和“is not”呢?
当需要判断某字段是否为null时,即所有“where”的后面都是“is null”、“is not null”;
当需要设置某字段为null时,即insert into和update set之后,都要用“= null”。

初识jQuery

什么是jQuery?

jQuery是一个JavaScript函数库。

通过 jQuery,可以选取(查询,query) HTML 元素,并对它们执行”操作”(actions)。

jQuery 语法是通过选取 HTML 元素,并对选取的元素执行某些操作。

基础语法: $(selector).action()

其中选择器(selector)可以使用CSS的各种选择器,以及基于XPath的一些组合和扩展。

操作(action)则是各种方法,其中包括各种事件处理方法,如click()、hover()等。

对网页中的元素进行取值、设置是DOM的常用操作,使用jQuery可以大大简化这些操作。以下是一些简单的实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//获取id="name"的表单元素(如input、select等)的值
var name = $("#name").val();

//设置id="name"的表单元素(如input、select等)的值为"ZhangSan"
$("#name").val("ZhangSan");

//获取id="abc"的HTML元素的innerText值
var txt = $("#abc").text();

//设置id="abc"的HTML元素的innerHTML值为把原来的值加上加粗标记
$("#abc").html("<strong>" + $("#abc").html() + "</strong>");

//设置class="left"的HTML元素的CSS属性
$(".left").css({"text-align":"left","margin-left":"10px"});

//文档中所有<p>标签隐藏
$("p").hide();

Javascript获取当前月份的最大天数

JAVASCRIPT获取前一天、后一天这篇日志中,简单介绍了Javascript时间日期对象Date的几种构造方法,其中有一种方法可以调用年、月(0-11)、日(1-31)、时(0-59)、分(0-59)、秒(0-59)、毫秒(0-999)参数来生成时间日期,其中年、月是必须的,其他可以选填。

1
2
3
4
5
//生成"2019-12-15 12:15:34.234"
var dt = new Date(2019,11,15,12,15,34,234);

//生成"2019-12-01 00:00:00.000"
var dt = new Date(2019,11);

当输入的参数的值超出该参数的取值范围时,构造方法会自动处理。

1
2
3
4
5
//生成"2020-01-01"
var dt = new Date(2019,12,1)

//生成"2019-02-04"
var dt = new Date(2019,0,35)

利用这个特性,就可以很方便的获取当前月份的最大天数,具体方法是传入月份值为下个月的月份值,日期值为0。因为日期值的范围是1-31,输入0,Date对象就会自动跳到上个月的最后一天,然后调用getDate()方法得到的就是当前月份的最大天数了。

1
2
3
//比如当前日期是"2019-12-14",执行后获取的maxDate值就是"31"
var dt = new Date("2019-12-14");
var maxDate = new Date(dt.getFullYear(),dt.getMonth()+1,0).getDate();

Javascript获取前一天、后一天

Javascript时间日期对象Date提供了十分方便的日期、时间构造方法,以及相当全面的获取、设置具体时间单位的值的方法。

构造方法

Javascript可以使用以下方法来构造一个时间日期对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
//获取当前时间
var d = new Date();

//从1970年1月1日0时起的毫秒数
var d = new Date(milliseconds);

//时间日期字符串:"2019-12-14",或者"2019-12-14 13:23:41"
//支持的日期格式有:年-月-日、年/月/日、月-日-年、月/日/年
var d = new Date(dateString);

//按顺序依次输入年、月、日、时、分、秒、毫秒参数
//至少要输入year、month两个参数,后面的都是可选
var d = new Date(year, month, day, hours, minutes, seconds, milliseconds);

常用取值、设值方法

Date对象提供了getFullYear()、getMonth()、getDate()、getHours()、getMinutes()、getSeconds()、getMilliseconds()七个方法来分别获取年、月(0-11)、日(1-31)、时(0-23)、分(0-59)、秒(0-59)、毫秒(0-999)的值,以及getDay()方法获取星期几(0-6)。

同时,提供了带UTC的八个方法getUTCFullYear()、getUTCMonth()、getUTCDate()、getUTCHours()、getUTCMinutes()、getUTCSeconds()、getUTCMilliseconds()、getUTCDay()用于获取世界时的年、月、日、时、分、秒、毫秒和星期几。

当然也提供了对应的set方法(除了星期几不能设置):setFullYear()、setMonth()、setDate()、setHours()、setMinutes()、setSeconds()、setMilliseconds(),setUTCFullYear()、setUTCMonth()、setUTCDate()、setUTCHours()、setUTCMinutes()、setUTCSeconds()、setUTCMilliseconds()。

另外,还有可以把时间转换为1970年1月1日起始的毫秒数(以下简称毫秒数)的方法getTime(),相应的方法UTC()则是根据世界时返回毫秒数。perse()方法可以把指定的时间日期字符串转换成毫秒数。

使用get、set方法,可以很方便的获取某个日期的前一天、后一天,当然,前一月、后一月,前几天、后几天,前几秒、后几秒,前几年、后几年,都是一样的道理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var dt = new Date();

//设置日期为下一天,时分秒等不变
dt = dt.setDate(dt.getDate() + 1);

//设置月份为上一月,如果date值大于当前月最大值,多出来的天数会变成当前月份的date值
//比如当前日期是2019-03-03,执行后就变成2019-02-03
//比如当前日期是2019-03-31,执行后就变成2019-03-03
dt = dt.setMonth(dt.getMonth() - 1);

//设置年份为十年后,也有例外情况,闰年的2月29日,增减年份到非闰年,会变成3月1日
dt = dt.setFullYear(dt.getFullYear() + 10);

//设置时间为50秒后
dt = dt.setSeconds(dt.getSeconds() + 50);

Date对象会自动处理超出范围的数据,使用起来非常方便。

常用转换字符串方法

toDateString() 把 Date 对象的日期部分转换为字符串。
toISOString() 使用 ISO 标准返回字符串的日期格式。
toJSON() 以 JSON 数据格式返回日期字符串。
toLocaleDateString() 根据本地时间格式,把 Date 对象的日期部分转换为字符串。
toLocaleTimeString() 根据本地时间格式,把 Date 对象的时间部分转换为字符串。
toLocaleString() 据本地时间格式,把 Date 对象转换为字符串。
toString() 把 Date 对象转换为字符串。
toTimeString() 把 Date 对象的时间部分转换为字符串。
toUTCString() 根据世界时,把 Date 对象转换为字符串。