星期二, 一月 23, 2007
星期五, 一月 19, 2007
Tips,VBA里如何扩展一个文本框TextBox的的长度,超过255限制
因为VBA里TextBox对象通过程序操作,只能复制最多256个字符。但通过UI确可以操作基本上
没限制的字符操作,真是邪门。
最终发现程序实现,无限制文本框操作技巧
Dim ctl1 As Shape
datasheetName = "Sheet1"
MyStr ="有1千个字符"
On Error Resume Next'如果不存在,删除会出错
Sheets("Sheet1").Shapes("recommend").Delete
Set ctl1 = Sheets("Sheet1").Shapes.AddTextbox(msoTextOrientationHorizontal, 0, 200, 450, 500)
ctl1.TextFrame.Characters.Text = left(MyStr,200)
ctl1.Name = "recommend"
'注意代码,perfect
For a = 1 To WorksheetFunction.Ceiling(Len(MyStr) / 200, 1)
ctl1.TextFrame.Characters((a * 200) + 1).Insert String:=Mid(MyStr, (a * 200) + 1, 200)
Next a
For Each ctl In Sheets(datasheetName).Shapes
Debug.Print TypeName(ctl) & " " & Left(ctl.Name, 8)
Next
星期四, 十二月 21, 2006
Tips,VBA里如何扩展一个注释的的长度,超过255限制
但NoteText只能允许255个字符,这是经常不够的。
要想使用更多的字符VBA里的comment对象允许32K的字符说明。
同样,修改 上一个tips的代码如下,就可以使用最多到32K的字符了。
With Cells(1,1).AddComment
.text "说明,最多32k"
.Shape.TextFrame.AutoSize = False
.Shape.width = 400
End With
这里.AddComment是很重要的手法 。
星期三, 十二月 20, 2006
Tips,VBA里如何扩展一个注释的宽度,避免自动折行
.NoteText "我的注释啊。。。。。。。。。。。。。。"
.Comment.Shape.TextFrame.AutoSize = False
.Comment.Shape.width = 400
End With
.comment.shape.width 是关键语句
星期五, 十二月 08, 2006
Java 5 注释功能的一点小知识。
1. Target:用来指定这个注释(Annotation)是为哪种类型而定义的。比如,这个类型可能只是为method定义的。比如override,不能用@override来修饰class或者field。
2.Retention:Retention的策略可以从以下三种中选取:- RetentionPolicy.SOURCE:编译器编译之后会会从class file中除去注释(Annotation)。
- Retention.CLASS:注释(Annotation)保留在class file中,但是VM不会处理。
- RetentionPolicy.RUNTIME,:注释(Annotation)保留在class file,VM会进行处理。
请注意,如果你希望在运行时查找到这些注释在什么地方被用到,一定要在定义注释的时候,选择RetentionPolicy.RUNTIME,否则即使你用注释修饰了类变量或者方法,在运行时也没有办法获得这个信息的。
3.Documented:这个注释(Annotation)将作为public API的一部分。
4.Inherited : 假设注释(Annotation)定义的时候使用了Inherited,那么如果这个注释(Annotation)修饰某个class,这个类的子类也被这个注释(Annotation)所修饰。
J2SE的内建注释(build-in annotation)
在程序中不仅可以使用自己定义的注释,还可以使用J2SE5.0中内建的注释类型。下面我们就详细来介绍J2SE5.0提供的注释类型。J2SE 5.0中预定义了三种注释注释类型:
Override :java.lang.Override 表示当前的方法重写了父类的某个方法,如果父类的对应的方法并不存在,将会发生编译错误。
Deprecated:java.lang.Deprecated 表示 并不鼓励使用当前的方法或者域变量。
SuppressWarnings: java.lang.SuppressWarnings关闭编译器告警,这样,在编译1.5之前的代码的时候,不会出现大量不关心的无关的告警
一个最小例子:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Copyright { String value();
}
星期二, 十一月 28, 2006
Java1.5泛型指南
JDK1.5中引入了对java语言的多种扩展,泛型(generics)即其中之一。
这个教程的目标是向您介绍java的泛型(generic)。你可能熟悉其他语言的泛型,最著名的是C++的模板(templates)。如果这样,你很快就会看到两者的相似之处和重要差异。如果你不熟悉相似的语法结构,那么更好,你可以从头开始而不需要忘记误解。
Generics允许对类型进行抽象(abstract over types)。最常见的例子是集合类型(Container types),Collection的类树中任意一个即是。
下面是那种典型用法:
List myIntList = new LinkedList();// 1
myIntList.add(new Integer(0));// 2
Integer x = (Integer) myIntList.iterator().next();// 3
第3 行的类型转换有些烦人。通常情况下,程序员知道一个特定的list里边放的是什么类型的数据。但是,这个类型转换是必须的(essential)。编译器只能保证iterator返回的是Object类型。为了保证对Integer类型变量赋值的类型安全,必须进行类型转换。
当然,这个类型转换不仅仅带来了混乱,它还可能产生一个运行时错误(run time error),因为程序员可能会犯错。
程序员如何才能明确表示他们的意图,把一个list中的内容限制为一个特定的数据类型呢?这是generics背后的核心思想。这是上面程序片断的一个泛型版本:
以下是引用片段:
List<Integer> myIntList = new LinkedList<Integer>(); // 1
myIntList.add(new Integer(0)); // 2
Integer x = myIntList.iterator().next(); // 3
注意变量myIntList的类型声明。它指定这不是一个任意的List,而是一个Integer的List,写作:List< Integer>。我们说List是一个带一个类型参数的泛型接口(a generic interface that takes a type parameter),本例中,类型参数是Integer。我们在创建这个List对象的时候也指定了一个类型参数。
另一个需要注意的是第3行没了类型转换。
现在,你可能认为我们已经成功地去掉了程序里的混乱。我们用第1行的类型参数取代了第3行的类型转换。然而,这里还有个很大的不同。编译器现在能够在编译时检查程序的正确性。当我们说myIntList被声明为List<Integer>类型,这告诉我们无论何时何地使用myIntList变量,编译器保证其中的元素的正确的类型。与之相反,一个类型转换说明程序员认为在那个代码点上它应该是那种类型。
实际结果是,这可以增加可读性和稳定性(robustness),尤其在大型的程序中。
2. 定义简单的泛型
下面是从java.util包中的List接口和Iterator接口的定义中摘录的片断:
public interface List<E> {
void add(E x);
Iterator<E> iterator();
}
public interface Iterator<E> {
E next();
boolean hasNext();
}
这些都应该是很熟悉的,除了尖括号中的部分,那是接口List和Iterator中的形式类型参数的声明(the declarations of the formal type parameters of the interfaces List and Iterator)。
类型参数在整个类的声明中可用,几乎是所有可是使用其他普通类型的地方(但是有些重要的限制,请参考第7部分)。
(原文:Type parameters can be used throughout the generic declaration, pretty much where you would use ordinary types (though there are some important restrictions; see section 7))
在介绍那一节我们看到了对泛型类型声明List(the generic type declaration List)的调用,如List<Integer>。在这个调用中(通常称作一个参数化类型a parameterized type),所有出现形式类型参数(formal type parameter,这里是E)都被替换成实体类型参数(actual type argument)(这里是Integer)。
你可能想象,List<Integer>代表一个E被全部替换成Integer的版本:
public interface IntegerList {
void add(Integer x)
Iterator<Integer> iterator();
}
这种直觉可能有帮助,但是也可能导致误解。
它有帮助,因为List<Integer>的声明确实有类似这种替换的方法。
它可能导致误解,因为泛型声明绝不会实际的被这样替换。没有代码的多个拷贝,源码中没有、二进制代码中也没有;磁盘中没有,内存中也没有。如果你是一个C++程序员,你会理解这是和C++模板的很大的区别。
一个泛型类型的声明只被编译一次,并且得到一个class文件,就像普通的class或者interface的声明一样。
类型参数就跟在方法或构造函数中普通的参数一样。就像一个方法有形式参数(formal value parameters)来描述它操作的参数的种类一样,一个泛型声明也有形式类型参数(formal type parameters)。当一个方法被调用,实参(actual arguments)替换形参,方法体被执行。当一个泛型声明被调用,实际类型参数(actual type arguments)取代形式类型参数。
一个命名的习惯:我们推荐你用简练的名字作为形式类型参数的名字(如果可能,单个字符)。最好避免小写字母,这使它和其他的普通的形式参数很容易被区分开来。许多容器类型使用E作为其中元素的类型,就像上面举的例子。在后面的例子中还会有一些其他的命名习惯。
3. 泛型和子类继承
让我们测试一下我们对泛型的理解。下面的代码片断合法么?
以下是引用片段:
List<String> ls = new ArrayList<String>(); //1
List<Object> lo = ls; //2
第1行当然合法,但是这个问题的狡猾之处在于第2行。
这产生一个问题:
一个String的List是一个Object的List么?大多数人的直觉是回答:“当然!”。
好,在看下面的几行:
以下是引用片段:
lo.add(new Object()); // 3
String s = ls.get(0); // 4: 试图把Object赋值给String
这里,我们使用lo指向ls。我们通过lo来访问ls,一个String的list。我们可以插入任意对象进去。结果是ls中保存的不再是String。当我们试图从中取出元素的时候,会得到意外的结果。
java编译器当然会阻止这种情况的发生。第2行会导致一个编译错误。
总之,如果Foo是Bar的一个子类型(子类或者子接口),而G是某种泛型声明,那么G<Foo>是G<Bar>的子类型并不成立!!
这可能是你学习泛型中最难理解的部分,因为它和你的直觉相反。
这种直觉的问题在于它假定这个集合不改变。我们的直觉认为这些东西都不可改变。
举例来说,如果一个交通部(DMV)提供一个驾驶员里表给人口普查局,这似乎很合理。我们想,一个List<Driver>是一个 List<Person>,假定Driver是Person的子类型。实际上,我们传递的是一个驾驶员注册的拷贝。然而,人口普查局可能往驾驶员list中加入其他人,这破坏了交通部的记录。
为了处理这种情况,考虑一些更灵活的泛型类型很有用。到现在为止我们看到的规则限制比较大。
4. 通配符(Wildcards)
考虑写一个例程来打印一个集合(Collection)中的所有元素。下面是在老的语言中你可能写的代码:
以下是引用片段:
void printCollection(Collection c) {
Iterator i = c.iterator();
for (int k = 0; k < c.size(); k++) {
System.out.println(i.next());
}
}
下面是一个使用泛型的幼稚的尝试(使用了新的循环语法):
以下是引用片段:
void printCollection(Collection<Object> c) {
for (Object e : c) {
System.out.println(e);
}
}
问题是新版本的用处比老版本小多了。老版本的代码可以使用任何类型的collection作为参数,而新版本则只能使用Collection<Object>,我们刚才阐述了,它不是所有类型的collections的父类。
那么什么是各种collections的父类呢?它写作: Collection<?>(发音为:"collection of unknown"),就是,一个集合,它的元素类型可以匹配任何类型。显然,它被称为通配符。我们可以写:
以下是引用片段:
void printCollection(Collection<?> c) {
for (Object e : c) {
System.out.println(e);
}
}
现在,我们可以使用任何类型的collection来调用它。注意,我们仍然可以读取c中的元素,其类型是Object。这永远是安全的,因为不管collection的真实类型是什么,它包含的都是objects。但是将任意元素加入到其中不是类型安全的:
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // 编译时错误
因为我们不知道c的元素类型,我们不能向其中添加对象。
add方法有类型参数E作为集合的元素类型。我们传给add的任何参数都必须是一个未知类型的子类。因为我们不知道那是什么类型,所以我们无法传任何东西进去。唯一的例外是null,它是所有类型的成员。
另一方面,我们可以调用get()方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object,因此把get的返回值赋值给一个Object类型的对象或者放在任何希望是Object类型的地方是安全的。
4.1. 有限制的通配符(Bounded Wildcards)
考虑一个简单的画图程序,它可以用来画各种形状,比如矩形和圆形。
为了在程序中表示这些形状,你可以定义下面的类继承结构:
以下是引用片段:
public abstract class Shape {
public abstract void draw(Canvas c);
}
public class Circle extends Shape {
private int x, y, radius;
public void draw(Canvas c) { // ...
}
}
public class Rectangle extends Shape {
private int x, y, width, height;
public void draw(Canvas c) {
// ...
}
}
这些
这些类可以在一个画布(Canvas)上被画出来:
public class Canvas {
public void draw(Shape s) {
s.draw(this);
}
}
所有的图形通常都有很多个形状。假定它们用一个list来表示,Canvas里有一个方法来画出所有的形状会比较方便:
public void drawAll(List<Shape> shapes) {
for (Shape s : shapes) {
s.draw(this);
}
}
现在,类型规则导致drawAll()只能使用Shape的list来调用。它不能,比如说对List<Circle>来调用。这很不幸,因为这个方法所作的只是从这个list读取shape,因此它应该也能对List<Circle>调用。我们真正要的是这个方法能够接受一个任意种类的shape:
public void drawAll(List<? extends Shape> shapes) { //..}
这里有一处很小但是很重要的不同:我们把类型 List<Shape> 替换成了 List<? extends Shape>。现在drawAll()可以接受任何Shape的子类的List,所以我们可以对List<Circle>进行调用。
List<? extends Shape>是有限制通配符的一个例子。这里?代表一个未知的类型,就像我们前面看到的通配符一样。但是,在这里,我们知道这个未知的类型实际上是Shape的一个子类(它可以是Shape本身或者Shape的子类而不必是extends自Shape)。我们说Shape是这个通配符的上限(upper bound)。
像平常一样,要得到使用通配符的灵活性有些代价。这个代价是,现在像shapes中写入是非法的。比如下面的代码是不允许的:
public void addRectangle(List<? extends Shape> shapes) {
shapes.add(0, new Rectangle()); // compile-time error!
}
你应该能够指出为什么上面的代码是不允许的。因为shapes.add的第二个参数类型是? extends Shape ??一个Shape未知的子类。因此我们不知道这个类型是什么,我们不知道它是不是Rectangle的父类;它可能是也可能不是一个父类,所以这里传递一个Rectangle不安全。
有限制的通配符正是我们解决DMV给人口普查局传送名单的例子所需要的。我们的例子假定数据用一个姓名(String)到people(用Person或其子类来表示,比如 Driver)。Map<K,V>是一个有两个类型参数的泛型类型的例子,表示map的键key和值value。
再一次,注意形式类型参数的命名习惯??K代表keys,V代表vlaues。
public class Census {
public static void addRegistry(Map<String, ? extends Person> registry) { ...}
}...
Map<String, Driver> allDrivers = ...;
Census.addRegistry(allDrivers);
5. 泛型方法
考虑写一个方法,它用一个Object的数组和一个collection作为参数,完成把数组中所有object放入collection中的功能。
下面是第一次尝试:
static void fromArrayToCollection(Object[] a, Collection<?> c) {
for (Object o : a) {
c.add(o); // 编译期错误
}
}
现在,你应该能够学会避免初学者试图使用Collection<Object>作为集合参数类型的错误了。或许你已经意识到使用 Collection<?>也不能工作。会议一下,你不能把对象放进一个未知类型的集合中去。
解决这个问题的办法是使用generic methods。就像类型声明,方法的声明也可以被泛型化??就是说,带有一个或者多个类型参数。
static <T> void fromArrayToCollection(T[] a, Collection<T> c){
for (T o : a) {
c.add(o); // correct
}
}
我们可以使用任意集合来调用这个方法,只要其元素的类型是数组的元素类型的父类。
Object[] oa = new Object[100];
Collection<Object> co = new ArrayList<Object>();
fromArrayToCollection(oa, co);// T 指Object
String[] sa = new String[100];
Collection<String> cs = new ArrayList<String>();
fromArrayToCollection(sa, cs);// T inferred to be String
fromArrayToCollection(sa, co);// T inferred to be Object
Integer[] ia = new Integer[100];
Float[] fa = new Float[100];
Number[] na = new Number[100];
Collection<Number> cn = new ArrayList<Number>();
fromArrayToCollection(ia, cn);// T inferred to be Number
fromArrayToCollection(fa, cn);// T inferred to be Number
fromArrayToCollection(na, cn);// T inferred to be Number
fromArrayToCollection(na, co);// T inferred to be Object
fromArrayToCollection(na, cs);// compile-time error
注意,我们并没有传送真实类型参数(actual type argument)给一个泛型方法。编译器根据实参为我们推断类型参数的值。它通常推断出能使调用类型正确的最明确的类型参数(原文是:It will generally infer the most specific type argument that will make the call type-correct.)。
现在有一个问题:我们应该什么时候使用泛型方法,又什么时候使用通配符类型呢?
为了理解答案,让我们先看看Collection库中的几个方法。
public interface Collection<E> {
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
}
我们也可以使用泛型方法来代替:
public interface Collection<E> {
<T> boolean containsAll(Collection<T> c);
<T extends E> boolean addAll(Collection<T> c);
// hey, type variables can have bounds too!
}
但是,在 containsAll 和 addAll中,类型参数T 都只使用一次。返回值的类型既不依赖于类型参数(type parameter)也不依赖于方法的其他参数(这里,只有简单的一个参数)。这告诉我们类型参数(type argument)被用作多态(polymorphism),它唯一的效果是允许在不同的调用点,可以使用多种实参类型(actual argument)。如果是这种情况,应该使用通配符。通配符就是被设计用来支持灵活的子类化的,这是我们在这里要强调的。
泛型函数允许类型参数被用来表示方法的一个或多个参数之间的依赖关系,或者参数与其返回值的依赖关系。如果没有这样的依赖关系,不应该使用泛型方法。
(原文: Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn’t such a dependency, a generic method should not be used.)
一前一后的同时使用泛型方法和通配符也是可能的。下面是方法 Collections.copy():
class Collections {
public static <T> void copy(List<T> dest, List<? extends T> src){...}
}
注意两个参数的类型的依赖关系。任何被从源list从拷贝出来的对象必须能够将其指定为目标list(dest) 的元素的类型??T类型。因此源类型的元素类型可以是T的任意子类型,我们不关心具体的类型。
copy方法的签名使用一个类型参数表示了类型依赖,但是使用了一个通配符作为第二个参数的元素类型。我们也可以用其他方式写这个函数的签名而根本不使用通配符:
class Collections {
public static <T, S extends T> void copy(List<T> dest, List<S> src){...}
}
这也可以,但是第一个类型参数在dst的类型和第二个参数的类型参数S的上限这两个地方都有使用,而S本身只使用一次,在src的类型中??没有其他的依赖于它。这意味着我们可以用通配符来代替S。使用通配符比声明显式的类型参数更加清晰和准确,所以在可能的情况下使用通配符更好。
通配符还有一个优势式他们可以在方法签名之外被使用,比如field的类型,局部变量和数组。这就有一个例子。
回到我们的画图问题,假定我们想要保持画图请求的历史记录。我们可以把历史记录保存在Shape类的一个静态成员变量里,在drawAll() 被调用的时候把传进来的参数保存进历史记录:
static List<List<? extends Shape>> history = new ArrayList<List<? extends Shape>>();
public void drawAll(List<? extends Shape> shapes) {
history.addLast(shapes);
for (Shape s: shapes) {
s.draw(this);
}
}
最终,再说一下类型参数的命名习惯。
我们使用T 代表类型,无论何时都没有比这更具体的类型来区分它。这经常见于泛型方法。如果有多个类型参数,我们可能使用字母表中T的临近的字母,比如S。如果一个泛型函数在一个泛型类里边出现,最好避免在方法的类型参数和类的类型参数中使用同样的名字来避免混淆。
星期五, 十一月 17, 2006
JBOSS如何同JVMSTAT 远程remote一起工作?
1.JBOSS 运行jdk 5.0
2.JBoss 运行 j2sdk 1.4.2
1.JBOSS 运行jdk 5.0
1.1 启动参数加入JAVA_OPTS="$JAVA_OPTS -XX:+UsePerfData"
1.2 然后在运行jstatd的地方建立一个policy文件。
jstatd.policy
grant codebase "file:${java.home}/../lib/tools.jar" { permission java.security.AllPermission; };
1.3 启动jstatd,直接在命令行运行jdk 5.0自带的 {jdk5.0_home}\bin\jstatd
1.4 确认Jboss和jstatd都一起运行 ,运行jdk 5.0自带的jps 得到如下结果:
5911 Main
5776 Jstatd
6075 Jps
1.5 再客户段 运行 jvmstat 3.0 bat或bin目录下的的visualgc.cmd 5911@szse199
注意:hostName必须用域名.
得到如下图片.

2.JBoss 运行 j2sdk 1.4.2
2.1 首先下载.jvmstat 2.0.
展开到一个目录下比如c:\jvmstat.及服务器上/root/jvmstat.
2.2 配置服务器端的policy.
设置 export JVMSTAT_HOME=/root/jvmstat
到 $JVMSTAT_HOME/policies 目录下 配置policy.
configurepolicy PerfAgentAll.tmpl PerfAgent.policy
2.3 运行 perfagent (rmi registry server)
$JVMSTAT_HOME/bin/perfagent -p 12345
注意:-p 选择 在有端口冲突(1099)的情况下使用.
这样在远程使用的时候,需要指定端口
2.4 得到运行的lvmid
运行$JVMSTAT_HOME/bin/jvmps 得到jboss的lvmid
7565 org.jboss.Main
7701 jvmps.jar
7632 perfagent.jar
2.5 在远程client机器上运行监控程序.
c:\jvmstat\bat\visualgc.cmd 7565@szse199:12345
得到图形如上:
星期四, 十一月 16, 2006
如何使用JDK 5.0 Jconsole同Jboss 3.0.8 Later工作?
是非常好的工具。
如何同JBOSS 3.0.8SP1一起工作,的确花了一定的时间才正确配置。
1.JBOSS 3.0.8 SP1是可以在JDK 5。0下工作的版本,比之小的版本只能运行在jdk 1.4下。
目前不能通过远程工作。不知道怎么回事。Linux下配置.
Jboss配置
修改 bin\run.sh
加入以下代码:
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=12345"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
然后在其他机器下运行 jConsole连接服务器。如图。

星期三, 十一月 01, 2006
如何用Ado从数据库复制数据到Excel的Sheets里?
Sub runthis()
Dim conn As New ADODB.Connection
Dim rec As New ADODB.Recordset
Dim sql As String
connstr = "ODBC;DSN=development;Server=10.2.1.1;Port=3306;Database=Store;Uid=root;Pwd="
sql = "SELECT * FROM employee "
Sheets("test").Activate
With ActiveSheet.QueryTables.Add(Connection:=connstr, _
Destination:=Range("B1"), sql:=sql)
.Refresh
End With
Set rec = Nothing
Set conn = Nothing
Exit Sub
errorHandler:
MsgBox "RunThis 错误:" & Err.Description
End Sub
方法二:
Sub runthis()
Dim conn As New ADODB.Connection
Dim rec As New ADODB.Recordset
Dim sql As String
connstr = "Driver={MySQL ODBC 3.51 Driver};Server=10.2.1.1;Port=3306;Option=131072;Stmt=;Database=store;Uid=root;Pwd="
conn.Open connstr
rec.Open "SELECT * FROM employee ", conn
sql = "SELECT * FROM emp_M_BasicInfo "
Sheets("test").Activate
Sheets("test").Cells.Clear
'显示字段名
For lCount = 0 To rec.Fields.Count - 1
Cells(1, 1 + lCount).Value = rec.Fields(lCount).Name
Next lCount
'显示数据
linenum = 1
If Not rec.EOF Then
Cells(linenum + 1, 1).CopyFromRecordset rec
rec.NextRecordset
linenum = linenum + 1
End If
Set rec = Nothing
Set conn = Nothing
Exit Sub
errorHandler:
MsgBox "RunThis 错误:" & Err.Description
End Sub
星期一, 十月 23, 2006
Tips.Excle 格式化cells value to text 文本
with cells(1,1)
.Style.NumberFormat = "@"
End with
星期五, 十月 13, 2006
Linux用Sendmail 发送 附件
#!/bin/sh
From="sunose@g.com"
To="sunose@g.com"
Subject="Sendmmail with attachment use uuencode"
(
echo "Subject: $Subject"
echo "body"
echo ""
uuencode $1 $1
) | /usr/sbin/sendmail -f$From $To
exit 0
Linux下Sendmail 配置成为邮件转发及避免DNS查询
一般语法转换为 m4 /etc/mail/sendmailmc > /etc/sendmail.cf
1。配置Sendmail作为邮件转发网关。
目的:做为内网,外网之间的Email集中,发散服务器。
可以把所有内网的Email通过一台Email发送到可以访问外网的服务器
配置.
1.1 直接修改sendmail.cf DS属性.
在Sendmail.cf里找到smart relay host DS 在后面加入需要转发到的中心Email网关
服务器的domain name
如 DSsmtp.microsft.com
1.2 修改sendmail.mc
加入:define(`SMART_HOST',`smtp.microsft.com')
然后用命令m4 编译成sendmail.cf.启动sendmail 就可以使用了。
上面的方法有个缺点,就是 网关服务器必须要有正规的域民,如果没有在发送email的时候,跟踪email
sendmail -v gate@microsft.com 会出现 (Reason 550 Host Unknown)的错误。
如何避免这个问题呢?这个问题就直接引出下面问题。
Sendmail发送Email的时候,如何避免查询DNS?
2. 配置Sendmail 发送Email不要查询DNS.
在sendmail.mc 文件里加入如下语句:
FEATURE(`nodns')dnl
然后通过 m4生成 sendmail.cf文件,并在提示下,建立/etc/mail/service.switch文件
文件内容包括如下:
hosts files
aliases files
注释:
hosts files 让sendmail的dns查询只查询/etc/hosts文件。
你可以在hosts文件里加入 ip 服务器名.
aliases files 让sendmail 查询/etc/mail/aliases
启动 sendmail /etc/init.d/sendmail restart 之后。
再用 sendmail -v xxx@microsft.com
就可以看到发送成功的消息了。如下
220 yourseve.name ESMTP Service ready at Fri, 13 Oct 2006 13:21:34 +0800
>>> EHLO localhost.localdomain
250-Email.Gateway Hello localhost.localdomain ([10.2.5.240]), pleased to meet you
250-HELP
250-SIZE 10240000
250 PIPELINING
>>> MAIL From:
250 root@localhost.localdomain... Sender OK
>>> RCPT To:
250 gate@microsft.com... Recipient OK
>>> DATA
354 Enter message, end with "." on a line by itself
>>> .
250 Message accepted for delivery
gate@microsft.com... Sent (Message accepted for delivery)
Closing connection to Email.gatway
>>> QUIT
星期二, 十月 10, 2006
Tips:Vba合并Excel的单元格
With Selection
.MergeCells = True
End With
任意多个对象都有.MergeCells的属性。
比如想把第一行合并。
With Rows(1)
.MergeCells = True
End With
星期四, 九月 28, 2006
Tips:Excle filter row copy to new sheet.
注意红色的关键代码。
'把包含某一个数字的记录,
'全部复制到result 工作簿里
'用户选择的range范围
Sub findByNumber()
Dim rng As Range
Dim newrng As Range
Dim Tools As New Toolkit
Dim choice As Integer
Dim cell As Object
Dim rRow As Range
Dim inyes As Boolean
Dim realnumber As Integer
Dim name As String
Dim counter As Integer
inyes = False
On Error Resume Next
counter = 1
choice = Application.InputBox("输入包含的数字", "查找的数字", Type:=1)'必须为数字
Set rng = Application.InputBox("选择数据范围", "选择数据", Selection.Address, , , , , 8)
If rng Is Nothing Then
MsgBox "你没有选择数据,不能继续"
Exit Sub
End If
name = rng.Parent.name
Add_Sheet ("result")
realnumber = choice
Sheets(name).Activate
If realnumber = 0 Then
Else
On Error GoTo errorhandler
For Each rRow In rng.Rows
inyes = False
For Each cell In rRow.Cells
If cell.value = realnumber Then '行中某一列的值同用户输入的值相等,则该行复制到result
inyes = True
rRow.Copy
Sheets("result").Activate
Sheets("result").Cells(counter, 1).Select
Sheets("result").Paste
counter = counter + 1
Sheets(name).Activate
Exit For
End If
Next 'for
Next
End If
Sheets("result").Activate
Exit Sub
errorhandler:
MsgBox Err.Description & Err.Source
End Sub
星期二, 九月 26, 2006
Tips:Excel sort by Each Column of Row
不能按照每一行第一列来排序。
必须自己编写一个方法来提供这个功能。
'iWhichWay as xlAscending 或 xlDescending,见Excel 2003 VBA 参考手册
Function SortRows(ByVal iWhichWay As Integer, rng As Range)
Dim rRow As Range
Dim parentSheet As String
parentSheet = rng.Parent.Name
Sheets(parentSheet).Activate '可以在任意sheet工作薄里对数据
'xlAscending,xlDescending
For Each rRow In rng.Rows
rRow.Sort Key1:=Range(rRow.Cells(1).Address), Order1:=iWhichWay , _
OrderCustom:=1, MatchCase:=False, Orientation:=xlLeftToRight, _
DataOption1:=xlSortNormal
Next
End Function
星期六, 九月 23, 2006
tips:excel vba 等待一段时间继续执行
对此方法缺点有是没有直接方法来确定准确的时间, 程序将运行循环量。 时间量取决于计算机的速度。 以下代码运行循环, 不起作用但占用时间。
Sub MyDelayMacro
For iCount = 1 to 1000
Next iCount
End Sub
方法 2: 使用 API 调用来暂停执行 Word
使用一个 API 调用来暂停执行 Word 用于固定的时间量。
Kernel32 包含函数, 暂停用于指定长的时间, 毫秒中指定程序的执行。 要使用函数, 必须首先在它将在其中使用模块的常规声明部分声明它:
Declare Sub Sleep Lib "kernel32" Alias "Sleep" _
(ByVal dwMilliseconds As Long)
使用以下语法来调用 Sleep 函数:
Sub Sleep()
Sleep 1000 'Implements a 1 second delay
End Sub
方法 3: 使用 OnTime 方法
使用 OnTime 方法来设置长的时间以运行其他宏命令之前暂停。 OnTime 方法使用以下语法:
表达式 .OnTime 时, 名称, Tolerance)
由于 名称 名称 参数需要, 运行一个宏的名称, 必须创建两个宏。 第一个宏包含 OnTime 方法调用和其他命令与宏相关。 第二个宏分配时间已过时运行。 第二个宏可以是 " 虚设 " 宏执行什么。
本示例运行名为 15 秒从示例宏 (MyMainMacro) 运行时间为 " MyDelayMacro " 宏。
Sub MyMainMacro()
' Pause for 15 seconds.
Application.OnTime When:=Now + TimeValue("00:00:15"), _
Name:="MyDelayMacro"
End Sub
Public Sub MyDelayMacro()
' Place your delayed macro commands here.
MsgBox "This macro runs after 15 seconds."
End Sub
有关获取与 VisualBasic 帮助 VisualBasicforApplications, 请单击文章编号以查看 Microsoft 知识库中相应:
星期五, 九月 22, 2006
Tips:Excel添加新的worksheet
Sub Add_Sheet(shtName As String)
Dim wSht As Worksheet
For Each wSht In Worksheets
If wSht.Name = shtName Then
Sheets(shtName).Cells.Clear '清除所有数据
Sheets(shtName).Activate 'focus
Exit Sub
End If
' MsgBox ActiveSheet.Name
Next wSht
Sheets.Add.Name = shtName
Sheets(shtName).Move After:=Sheets(Sheets.Count)
End Sub
星期四, 九月 21, 2006
tips:遍历(Iterator)Excel Range的数据。
For i = 1 To rng.row
For j=1 to rng.column
cells(i,j).value=??.
Next
counter = 1
For Each cell In rng
Cells(21, counter).Value = cell.Value
counter = counter + 1
Next
星期三, 九月 20, 2006
Excel Developer Tip: Pausing a Macro to Get a User-Selected Range
Sub ProblemCode()
Dim oRangeSelected As Range
On Error Resume Next
Set oRangeSelected = Application.InputBox("Please select a range of cells!", _
"SelectARAnge Demo", Selection.Address, , , , , 8)
If oRangeSelected Is Nothing Then
MsgBox "It appears as if you pressed cancel!"
Else
MsgBox "You selected: " & oRangeSelected.Address(external:=True)
End If
End Sub
这里的inpubox可以改变为一个editor,如果标准Excel显示。
星期五, 九月 08, 2006
开源的数学工具包。
http://jscience.org/ 是个提供一些数学方法的 java mathematics library
提供全部数学方法的函数库非常之少。
遗憾。